You might expect something like your array_values function to be a lot
faster than arrayskip, but according to my benchmarking in many cases
it is not.
array_values appears to start winning when there's seven or more
positional parameters. (i.e. 14 items in the list, seven of which need
to be removed.) Below that, PerlX::ArraySkip wins. (This is tested on
Perl 5.16.0 on a reasonably slow computer.)
An XS implementation of either might be fun to try. Also worth thinking
about would be some Devel::Declare trickery to detect:
arrayskip BAREWORD =>
at compile time and completely remove it from the op tree. In cases
where there wasn't a bareword (e.g. a quoted string, or a more complex
expression) then the arrayskip call would be left as-is. That would
incur a slight compile-time penalty, but eliminate the run-time penalty
altogether.
use Benchmark ':all';
use PerlX::ArraySkip 'skip';
sub give { die "ARGH" unless $_[0]==1 && $_[1]==2 && $_[2]==3 }
sub array_values { my $i; grep { $i++ % 2 } @_ }
cmpthese(200_000, {
AllInOne => sub { give(array_values foo => 1, bar => 2, baz => 3) },
ArraySkip => sub { give(skip foo => 1, skip bar => 2, skip baz => 3) },
});
cmpthese(200_000, {
LongAllInOne => sub { give(array_values foo => 1, bar => 2, baz => 3, quux => 4, quuux => 5, xyzzy => 6, garble => 7) },
LongArraySkip => sub { give(skip foo => 1, skip bar => 2, skip baz => 3, skip quux => 4, skip quuux => 5, skip xyzzy => 6, skip garble => 7) },
});
cmpthese(200_000, {
VeryLongAllInOne => sub { give(array_values foo => 1, bar => 2, baz => 3, quux => 4, quuux => 5, xyzzy => 6, garble => 7, alice => 8, bob => 9, carol => 10) },
VeryLongArraySkip => sub { give(skip foo => 1, skip bar => 2, skip baz => 3, skip quux => 4, skip quuux => 5, skip xyzzy => 6, skip garble => 7, skip alice => 8, skip bob => 9, skip carol => 10) },
});