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

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

Thread Previous | Thread Next
From:
Brian Fraser
Date:
September 28, 2011 18:15
Subject:
Re: [perl #100190] RFE: fix sprintf to be consistent with printf andbe useful!
Message ID:
CA+nL+na0XzynBz7Bdx5O3x7vRKhXLNrxfeNGmtFjJvB27xUVYQ@mail.gmail.com
On Wed, Sep 28, 2011 at 8:27 PM, Linda W <perl-diddler@tlinx.org> wrote:

> (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,  ;-).
>


I don't think so? It's relatively new, and used all the time in Modern Perl,
which came out less than a year ago. Plus it's a soft keyword, enabled by a
use version/feature. Seems like we ought to be encouraging more of these.
(it's also lovely for marketing. Ruby has puts. Python adds it automatically
to print. We have say.)


> 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
> people
> 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).
>
>
They totally work, once you run them under strict and fix them :P See doy's
reply. Sorry about that.


> 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
>     $!=$errno;
>     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;
>
>
That's ugly. :)


>
>
>   Like bleeding helps me...hey your prev example doesn't work...maybe it
> only worked while
> bleeding too? ;-)
>
>
Well, maybe your physician is a bit wacky and had you do some bloodletting.
But I'd report him in that case.


>
> 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)..
>
>
That's hardly my point. In fact, that's a huge strawman. Prototypes suck --
except when they don't. The only advice is not to use them[0]. But they do
have their place -- I would much rather use grep or map followed by a block
than by a sub declaration, for example, even if it's only a couple of extra
characters.

I had no idea about that line in perlsub though. I kind of want it removed
now, but that's another topic for another time.


>
> yup ... counterintuitive is right!...That's not Perl spirit,
> which is just supposed to "do the right thing"(c)-Perl  (and
> something useful!)...
>
>
It certainly does the right thing... Just not for you. I imagine Larry
thought it made sense, back in the day, and changing ages-old behavior under
people's feet isn't exactly nice, so chances are this isn't going to happen.
You are welcome to fix it and put it on CPAN though.
In fact, here you go, something to get you started:
BEGIN { *CORE::GLOBAL::sprintf = sub { CORE::sprintf( $_[0], @_[ 1 .. $#_ ]
); } }


> 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.


Eh.
my @list = ( q{, }, 1..10 );
say join @list; #whoops

Same with pack, link, etcetera. Basically, you are attempting to treat
built-ins as unprototyped functions, which sounds remarkably like a "Doctor,
it hurts when I do this" situation. Either stop doing that, or use the
&CORE:: magicks with bleadperl.

  There is no special type in perl (that I'm aware of),
> call 'FORMAT STRING'....
>
>
>
Well, to be pedantic, sure there is. But I wouldn't read the "sprintf
FORMAT, LIST" description in the docs so literally, otherwise sprintf's
first argument would be:

format MIND =
slightly disturbed
.

sprintf *MIND{FORMAT}, ...;



[0] http://www.perlmonks.org/?node_id=861966

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About