SPUG: idioms of late

Joshua Juran jjuran at gmail.com
Mon Jan 18 15:39:39 PST 2010

On Jan 18, 2010, at 12:04 PM, Fred Morris wrote:

> Lately I've found myself doing a lot of processing of lists... usually
> either listrefs, or a list of keys which can be looked up in a  
> hashref.
> I've found myself using a few idioms in place of for/while loops
> repeatedly, and I thought I'd share.
> $foo->{names} = [ map { my $x = $_; $x =~ s/\.$//o; $x; }
>                       @{$foo->{names}}
>                 ];
> That one munges a listref, stripping trailing dots off of all of the
> elements. The initial "$x = $_;" seems to be necessary. That one seems
> rather pythonic to me. Generally speaking they prefer that I use perl.

First of all, let me note that your use of /o does nothing, since the  
pattern doesn't contain any variables and therefore doesn't need to  
be recompiled in the first place.  You have to use a copy of $_  
because $_ is read-only in map.

$ time perl -e 'my @x = 0 .. 1000000; @x = map { my $x = $_; $x =~ s/ 
\.$//o; $x; } @x'

real    0m2.357s
user    0m2.078s
sys     0m0.271s

$ time perl -e 'my @x = 0 .. 1000000; @x = map { my $x = $_; $x =~ s/ 
\.$//; $x; } @x'

real    0m2.355s
user    0m2.076s
sys     0m0.271s

The operation you're repeating either shortens the value or does  
nothing to it.  There's no reason for any allocations whatsoever.   
But your example makes lots of copies, not even only to put them back  
where they came from, but replacing the original array with a newly  
constructed one.

The anti-functional-style for loop is well over twice as fast and  
less than a third of the keystrokes (for the loop itself).

$ time perl -e 'my @x = 0 .. 1000000; s/\.$// for @x'

real    0m0.950s
user    0m0.823s
sys     0m0.121s

I spend a lot of time in C++, and a little in assembler.

> printf "%s\n", join( "\t", @{$foo}{@FIELDS} );
> ..or..
> printf "%s\n", join( "\t", @{$foo}{qw/ fee fie foe /});
> That's kind of an interesting one because $foo is actually a hashref.
> Another variant of that which is useful is as part of, for instance,
> enforcing a "no quotes in SQL literals" rule:
> my ($name, $address, $city) =
>     map $dbh->quote($_), @{$self}{qw/ name address city /};
> my $sql .= "VALUES ($name, $address, $city)";

Please don't do this.  Let DBI generate your SQL statement for you.

I hope this sort of critique is what you were looking for.


More information about the spug-list mailing list