Thanks for the response. My problem is not really what it's doing as that's obvious by the results. My problem is more the how.
unshift when acting with one value is (sort of) moving everything up one slot, then filling in the new [0] slot.
However, when acting with multiple values, is it:
reversing the order of the incoming values then (move everything up one slot, fill in the new [0] slot) N times
or
count the incoming values, move everything up N slots, then fill in the N slots [0],[1],[2],... with the incoming values
My personal bet is on the second as it'd be faster. Admitted, this is not one of the all-time consuming questions about the Universe, but when something doesn't act the way I expect, I like to know how it achieves the result(s) that it gets. Or should I simply go with "No, I won't pay any attention to the man behind the curtain."?
And yes, thank you, I'll be fiddling with the debugger sooner or later.
| [reply] |
For reasons of symmetry this
unshift @a, @b means @a = ( @b, @a )
Much the same way as
push @a, @b means @a = ( @a, @b )
So no implicit reversing of @b.
HTH :)
| [reply] [d/l] [select] |
Therefore:
unshift @a, @b same* as push @b, @a
*But see clarification from choroba:
| [reply] [d/l] [select] |
Or should I simply go with "No, I won't pay any attention to the man behind the curtain."?
Yes. Perl functions generally do what they say on the tin :-)
Admitted, this is not one of the all-time consuming questions about the Universe, but when something doesn't act the way I expect, I like to know how it achieves the result(s) that it gets.
As far as I can tell from the internal implementation of pp_unshift and av_unshift, your guess that it's the latter (Edit 2: that is, shift the array up by N at once) appears to be correct. But as stated above, that should be considered an implementation detail that you don't need to worry about.
My personal bet is on the second as it'd be faster.
If concerned about performance, always measure first, using Benchmark and/or Devel::NYTProf.
Update: Actually, LanX's post here provides something more interesting to benchmark. I've also added a built-in test of the benchmarked code here.
use warnings;
use strict;
use Benchmark qw/cmpthese/;
use constant TEST => 0;
my $EXP = join $", 100..150, 1..50;
cmpthese(-2, {
unshift => sub {
my @array = 1..50;
my @add = 100..150;
unshift @array, @add;
"@array" eq $EXP or die "@array" if TEST;
},
loop => sub {
my @array = 1..50;
my @add = 100..150;
unshift @array, $_ for reverse @add;
"@array" eq $EXP or die "@array" if TEST;
},
concat => sub {
my @array = 1..50;
my @add = 100..150;
@array = ( @add, @array );
"@array" eq $EXP or die "@array" if TEST;
},
});
__END__
Rate loop concat unshift
loop 273062/s -- -19% -33%
concat 337646/s 24% -- -18%
unshift 409595/s 50% 21% --
| [reply] [d/l] [select] |