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.
Cheers,
Josh
More information about the spug-list
mailing list