I think I have misunderstood some aspects of argument passing to functions in Perl. What's the difference between func(\@array)
and func(@array)
?
AFAIK, in both functions, arguments are passed by reference and in both functions we can change the elements of @array
in the main program. So what's the difference? When should we use which?
@array = (1,2,3);
func(@array);
func(\@array);
sub func {
...
}
Also, how do I imitate pass-by-value in Perl? Is using @_
the only way?
AFAIK, in both functions, arguments are passed by reference and in both functions we can change the elements of @array in the main program.
"change the elements of", yes. However, in the func(@array)
case, the sub has no means to make other changes to the array (truncating it, pushing, popping, slicing, passing a reference to something else, even undef'ing it).
I would avoid using the term "passed by reference", since the mechanism is completely different than Perl's references. It is less overloaded :) to say that in the sub, @_
's elements start off aliased to the elements passed to the sub.
It's impossible to pass arrays to subs. Subs take a list of scalars for argument. (And that's the only thing they can return too.)
You can pass a reference to an array:
func(\@array)
You can pass the elements of an array:
func(@array)
When should we use which?
If you want to pass more than just the elements of the array (e.g. pass $x
, $y
and @a
), it can become tricky unless you pass a reference.
If you're going to process lists (e.g. sum mysub grep { ... } ...
), you might not want to pass a reference.
If you want to modify the array (as opposed to just modifying the existing elements of the array), you need to pass a reference.
It can be more efficient to pass a reference for long arrays, since creating and putting one reference on the stack is faster than creating an alias for each element of a large array. This will rarely be an issue, though.
It's usually decided by one of the first two of the above. Beyond that, it's mostly a question of personal preference.
Also, how do I imitate pass-by-value in Perl?
sub foo {
my ($x) = @_; # Changing $x doesn't change the argument.
...
}
sub foo {
my @a = @_; # Changing @a or its contents
... # doesn't change the arguments.
}
func(\@array)
passes a reference. func(@array)
passes a list (of the elements in @array
). As Keith pointed out, these elements are passed by reference. However, you can make a copy inside the sub in order to pass by value.
What you are after is this:
sub func {
my @array = @_;
}
This will pass a copy of the arguments of func
to @array
, which is a local variable within the scope of the subroutine.
Documentation here