tlm has asked for the wisdom of the Perl Monks concerning the following question:
Here's another question borne out of idle curiosity: what is the most efficient way to force a list context? I used to think that it'd be assigning to the empty list, but that's not the case, at least not always, as the results below show.
First, here's the set-up:
Two sets of benchmarks, corresponding to various ways of forcing list contexts on calls to two different functions: Perl's built-in lexicographic sort function (these are the s_* items), and gr, a simple implementation of a Guttman-Rosler sort (this is basically the subroutine guttros posted by friedo here; these are the g_* items). (The results will show that either set of benchmarks would have been sufficient illustration, but it's nice to have the extra datapoint by way of crosscheck.)use Benchmark 'cmpthese'; sub gr { # Guttman-Rosler transform map { substr( $_, 3 ) } sort map { sprintf( '%03d', /abc(\d+)xyz/ ) . $_ } @_; } srand 0; my @u = map 'abc' . int( rand 1000 ) . 'xyz', 1..500; cmpthese( -1, { s_aa => sub { my @s = sort @u }, s_fi => sub { ( sort @u )[ 0 ] }, s_na => sub { () = sort @u } } ); cmpthese( -1, { g_aa => sub { my @s = gr @u }, g_fi => sub { ( gr @u )[ 0 ] }, g_na => sub { () = gr @u } } );
And here are the results:
There you have it: fetching the first element unequivocally beats assigning to (). I find this very surprising. After all, fetching the first element requires some honest work, but assigning to a null list is something so nominal that I would have expected it to be pretty much the list counterpart of scalar.Rate s_aa s_na s_fi s_aa 1037/s -- -49% -49% s_na 2017/s 95% -- -1% s_fi 2036/s 96% 1% -- Rate g_na g_aa g_fi g_na 237/s -- 0% -14% g_aa 237/s 0% -- -14% g_fi 275/s 16% 16% --
The approaches above are what I could think of as likely candidates for the lowest-overhead list-forcing method. But the results tell me that my intuition on these matters is a poor guide. Are there more efficient methods?
More to the point, why isn't there a direct way to just tell perl we want a list context, just like we can do with scalar context? It's silly to have trick perl into it.
the lowliest monk
|
|---|