develooper Front page | perl.perl5.porters | Postings from September 2011

Re: [perl #100190] RFE: fix sprintf to be consistent with printf and be useful!

Thread Previous | Thread Next
Linda W
September 28, 2011 16:27
Re: [perl #100190] RFE: fix sprintf to be consistent with printf and be useful!
Message ID:

Brian Fraser wrote:
> Uh, you can already do all the stuff you request, y'know:
> my @arr = ( "%s\n", "hullo" );
> my $result = sprintf $arr[0], $arr[1..$#etc];
> say $result;
(I thought 'say' was deprecated?  Seems like adding a keyword just to 
add on some desired
line ending is a road to certain madness ... but .. hey,  ;-).
Ya know...for someone who talks like what they think they know what they
are talking about, they might wanna check their examples before telling 
that they can do "XXX", cuz your example doesn't work (and I wasted a 
bit of time
thinking you knew what you were talking about!  (dictionary, gullible: me).

So here's the stuff one would have to go through to get around this "WART":

"sub msg()", is an all-around msg routine that
      * adds newlines if you don't have one
      * can take an errno value as 1st arg and use the msg as output to die
      * take the 1st non errno value as an option format for the rest of 
the args;
      * else will print all the strings, sep w/default OFS (null by 
default), so spaces
        are responsiblity of the user.

Considering it was written in an afternoon (after wasting much of it 
trying to
hack around sprintf's limitations, (not to mention the 
$arname[1..$#arname] not working as
some suggested), don'texpect miracles.  However, _primitive_ cmdline 
testing shows
that it demonstrates the beauty of sprintf's versatility compared to 
printf (!!NOT!!).

If you don't like my code style, may you rot in Microsoft's laboratories!

#!/usr/bin/perl -w
use 5.12.0;
use Fatal;

use Readonly; sub RO(\[$@%]@) { goto &Readonly }

sub msg(@) {
  my @mp=@_;
  my $errno = shift @mp if $mp[0] =~ /^[-0-9]+$/;   # do we have a status?

  if (defined $mp[0] and
    $mp[0] =~ m{(^.*(?:(?:%|(?:[-\d.][a-zAA-Z]))|%)|\\).*$}) {
    $mp[0] =~ s{^(.*?)(?:\\n)?$}{$1};
    if ($errno) {
      $mp[0] .= ", Err=%s\n"; #add errno print  to format w/NL
      push @mp, "$!";   # and add errno as last arg
      if (0) {    # if this worked, would make life simple...
        die sprintf @mp;
      } elsif (0) {   #what lamer thought this worked in 5.12.0?
        die sprintf $mp[0], $mp[1..$#mp];
      } elsif (0) { # this only works  for 2 args+err code, so also broken
        die sprintf $mp[0], $mp[1], $mp[2], $mp[3];
      } else { # to handle var# args seems like eval is answer...?
          my $hack='sprintf "'. $mp[0] .'", ';
          for (my $i=1; $i<=$#mp; ++$i) {
            $hack .= ', $mp['."$i".']';
          $hack .= ';'."\n";
        die eval "$hack";
    } else {
      $mp[0] .= "\n";
      printf @mp;

  } else {
    return undef unless defined $mp[0];
    chomp $mp[$#mp];  #noformat so chomp any 'nl's off the last arg
    # if we have an err, then push printing of it onto end,
    # else restore  NL
    ($!=$errno, push @mp, ", Err=$!\n") if $errno;
    if ($errno) {
      die join $, ? $, : "", @mp;
    } else  {
      print @mp,"\n";
    return 1;
  } ## end sub msg($@)
} ## end sub msg($@)

#test code
msg @ARGV;

> Or if you think that's ugly, you can do this in blead:
> my @arr = ( "%s\n", "hullo" );
> my $result =&CORE::sprintf(@arr);
> say $result;
    Like bleeding helps me...hey your prev example doesn't work...maybe 
it only worked while
bleeding too? ;-)
> Printing to a scalar has also been in core for a while:
> open my $fh, ">", \my $scalar or die $!;
> say { $fh } "hullo";
> close($fh);
> say $scalar;
    I'll reserve judgement on that until I've tried it, give my history 
with a few other things you said
were working...

> I wouldn't call it a wart, any more than I'd call anything that uses 
> prototypes a wart.

You mean the prototypes that are 'awesome' and the only advice on them is:
   it's probably best to prototype new functions... 
    [as opposed to trying to retrofit old ones]...

If every function since that was written was prototyped....
everything would be (in the camel book and manpage)..

> Admittedly it's counterintuitive at first,

yup ... counterintuitive is right!...That's not Perl spirit,
which is just supposed to "do the right thing"(c)-Perl  (and
something useful!)...
> but expecting sprintf @arr to work would mean that open @arr should 
> also work, and so on; That road leads to madness.
open @arr would work?   Why?  It's NOT a simple list of scalers...
It's first arg is something to be *written to*.  Yeah, I could see the
argument, but, realistically, I'm looking at a command that ostensibly takes
a list of scalars.   There is no special type in perl (that I'm aware of),
call 'FORMAT STRING'....

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About