"always passes by reference"

Steven E. Harris sharris at nospam.primus.com
Tue Aug 1 14:24:07 EDT 2000


m.faassen at vet.uu.nl (Martijn Faassen) writes:

> Hm, I didn't work Perl worked like that without explicit dereferencing,
> but what do I know about Perl. :)

[...]

It acts like that for scalar variables passed to a function. Other
types like lists and hashes get "flattened out." The habit of passing
variables by explicit, "hard" reference that you may be recalling is
necessary when you need to preserve individual list structure over
several arguments.

Here's an example:

==================================================
#!/bin/perl

use strict;


sub foo
{
	print "\nfoo() args before: @_\n";
	foreach ( @_ )
	{
		print "arg: $_\n";
	}

	$_[0] = 1;
	print "foo() args after: @_\n";
}


my $bar2 = 2;
foo( $bar2 );

my @baz3 = ( 3, 4, 5 );
my @baz6 = ( 6, 7, 8 );
foo( @baz3, @baz6 );

my @baz9 = ( 9, 10, 11 );
my @baz12 = ( 12, 13, 14 );
foo( \@baz9, \@baz12 );

my $ref_baz12 = \@baz12;
foo( $ref_baz12 );

print <<"_EOF_";

after foo() calls:
bar2       = $bar2
baz3       = @baz3
baz6       = @baz6
baz9       = @baz9
baz12      = @baz12
ref_baz12  = $ref_baz12
_EOF_
==================================================

==================================================
[sample output]

foo() args before: 2
arg: 2
foo() args after: 1

foo() args before: 3 4 5 6 7 8
arg: 3
arg: 4
arg: 5
arg: 6
arg: 7
arg: 8
foo() args after: 1 4 5 6 7 8

foo() args before: ARRAY(0xd5ec0) ARRAY(0xd5f08)
arg: ARRAY(0xd5ec0)
arg: ARRAY(0xd5f08)
foo() args after: 1 ARRAY(0xd5f08)

foo() args before: ARRAY(0xd5f08)
arg: ARRAY(0xd5f08)
foo() args after: 1

after foo() calls:
bar2       = 1
baz3       = 1 4 5
baz6       = 6 7 8
baz9       = 9 10 11
baz12      = 12 13 14
ref_baz12  = 1
==================================================

Notice how the assignment within foo() to the first element of @_
changes the first element of @baz3. Within foo(), there was no way to
know that @baz3 and @baz6 were originally different lists. They got
flattened out into foo()'s @_.

Next, we pass two lists by explicit reference. Here, within foo(), @_
contains two separate list references. Since we blindly assign over
the first reference, we're really only changing a temporary reference
that was created in the call to foo().

Finally, If we create an explicit hard reference to @baz12 and call
foo() with it, you can it get obliterated by the assignment within
foo.

To summarize: In Perl, function parameters are always passed "by
reference," but these are not the same as variable references created
by the '\' operator or anonymous hash or list constructors. Function
parameter modifications always change the caller's variables. The
caller can also pass variables that happen to be references, and these
references get treated the same as any other *scalar* function
parameter.

Here's the relevant quote from "Programming Perl":

[Chapter 2, p112]
> The array @_ is a local array, but its values are implicit
> references to the actual scalar parameters. Thus, you can modify the
> actual parameters if you modify the corresponding element of
> @_. (This is rarely done, however, since it's so easy to return
> interesting values in Perl.

-- 
Steven E. Harris
Primus Knowledge Solutions, Inc.
http://www.primus.com



More information about the Python-list mailing list