Background
Perldoc for List::Util suggests that some uses of map may be replaced by reduce in order to avoid creating unnecessary intermadiate list:
For example, to find the total length of the all the strings in a list, we could use
$total = sum map { length } @strings;However, this produces a list of temporary integer values as long as the original list of strings, only to reduce it down to a single value again. We can compute the same result more efficiently by using reduce with a code block that accumulates lengths by writing this instead as:
$total = reduce { $a + length $b } 0, @strings;
That makes sense. However, reduce in order to work in this example needs "identity value", that would be prepended to input list:
$total = reduce { $a + length $b } 0, @strings;
# ^^^^^^^^^^^
That makes me think, doesn't 0, @strings create a new list, thus offset any gains from not creaing list in map?
Question
How does list interpolation ($scalar, @list) work in Perl? Does it involve copying elements from source list or is it done in some smarter way? My simple benchmark suggests copying taking place:
use strict;
use warnings;
use Benchmark qw/cmpthese/;
my @a1 = 1..10;
my @a2 = 1..100;
my @a3 = 1..1000;
my @a4 = 1..10000;
my @a5 = 1..100000;
my @a6 = 1..1000000;
cmpthese(10000, {
'a1' => sub { my @l = (0, @a1); },
'a2' => sub { my @l = (0, @a2); },
'a3' => sub { my @l = (0, @a3); },
'a4' => sub { my @l = (0, @a4); },
'a5' => sub { my @l = (0, @a5); },
'a6' => sub { my @l = (0, @a6); },
});
Results:
(warning: too few iterations for a reliable count)
Rate a6 a5 a4 a3 a2 a1
a6 17.6/s -- -90% -99% -100% -100% -100%
a5 185/s 952% -- -90% -99% -100% -100%
a4 1855/s 10438% 902% -- -90% -99% -100%
a3 17857/s 101332% 9545% 862% -- -91% -98%
a2 200000/s 1135940% 107920% 10680% 1020% -- -80%
a1 1000000/s 5680100% 540000% 53800% 5500% 400% --
Bonus question: If my assumptions are correct (i.e. 0, @strings creates a new list), does replacing map with reduce make sense?