Well, I was going to write a bit about passing by reference and passing by
value which the two replies so far have espoused, but when I did some
benchmarks I was a bit surprised.
First of all, for small arrays there is no noticable difference between
passing by ref and passing by value. There is no surprise there. But it
always amazes me how many experienced programmers insist on passing strings
around by reference and so making their code far more difficult to read.
Now suppose you have a large amount of data to pass to a sub, the question
you might want to ask first is:
Does Perl pass by array or by reference?
And, as with most things Perl, the answer is Yes!
When you pass something to a sub, it is passed by reference, but
as soon as you assign that to a new variable a copy is created and so it
looks as though it was passed by value.
Now suppose you take a reference to @_ you have in effect
passed by reference in a way that is transparent to the caller.
Why would you want to do this? Well for the very good reason that
you don't want to have to create references in the code that calls the
subs. It is obvious that using references is more complicated than using
straight variables, so if that can be hidden away in the sub it makes the
code a lot clearer which is a good thing
Now before I posted this, I wanted to test it. I started with this:
sub write_array_1{
my $file = shift;
my $r_array = \@_;
open FILE, ">$file" or die "failed to open $file ($!)";
print FILE @$r_array;
close FILE;
}
But the writing of the file was concealing the time taken for the
array passing, so I just made sure every element of the array was accessed:
use strict;
use warnings;
use Benchmark;
sub write_array_1{
my $file = shift;
my $r_array = \@_;
$_++ foreach @$r_array;
}
sub write_array_2{
my $file = shift;
my $r_array = shift;
$_++ foreach @$r_array;
}
sub write_array_31{
my $file = shift;
my @array = @_;
$_++ foreach @array;
}
my @array = ( 1..100000 );
my $filename = 'C:\users\jake\testing\arrayref.dat';
timethese(30, {
'Pass by ref transparently' => sub {write_array_1( $filename .
+ 1, @array );},
'Pass by ref explicitly' => sub {write_array_2( $filename .
+ 2, \@array );},
'Pass by value' => sub {write_array_3( $filename .
+ 3, @array );},
});
Benchmark: timing 30 iterations of Pass by ref explicitly, Pass by ref
+ transparently, Pass by value...
Pass by ref explicitly: 2 wallclock secs ( 1.84 usr + 0.00 sys = 1.
+84 CPU) @ 16.27/s (n=30)
Pass by ref transparently: 3 wallclock secs ( 2.94 usr + 0.00 sys =
+ 2.94 CPU) @ 10.21/s (n=30)
Pass by value: 4 wallclock secs ( 4.42 usr + 0.02 sys = 4.44 CPU) @
+ 6.76/s (n=30)
So passing by value is slower (as expected) but why is the explicit passing by
reference quicker than the transparent method? It's faster than passing by value
so it must be doing what it's supposed to, but not the same as the explicit
reference?
--
iakobski |