[lug] Perl - How to pass by Reference?
Tkil
tkil at scrye.com
Thu Mar 2 01:38:16 MST 2006
>>>>> "SH" == Siegfried Heintze <siegfried at heintze.com> writes:
SH> This is a great exercise that is not covered well in any of the
SH> tutorials I read when I was trying to learn perl. I found this
SH> lesson very painful.
Heh. My single most painful lesson was learning, finally, that $foo,
@foo, and %foo had absolutely nothing whatsoever to do with each
other. And that $foo[0] refers to the first element in @foo, with no
relation at all to $foo.
FWIW, Perl 6 is fixing that. :) I'll take a look in 2010 when it's
released...
SH> First: Why are you trying to pass by reference?
SH> There are easier alternatives like returning a list as the
SH> function value. The list would contain the changed values.
Probably not something that Bill is dealing with, but passing big
lists hither and yon gets pretty expensive.
Also, Perl object-oriented programming (POOP?) uses references
extensively, and having a solid understanding of them is a necessity
to be considered even a journeyman Perl programmer.
Having said that, if the reason that someone wants to pass a scalar by
reference is to (say) quote or unquote it, I'll agree with you that
using a purely-functional input-output model is much better.
There are also some weird applications where you are twiddling bits in
the guts of Perl; even now that UTF-8 support is pretty solid, there
are still times that you have to poke at Perl scalars and explicitly
nudge the UTF-8 flag. Check out the nastiness that is "_utf8_on" in
the Encode perldoc.
SH> You can pass a scalar by reference. Are you a C programmer? There
SH> are some analogs if you are.
SH> To pass a scalar by reference you insert the "\" in front of the
SH> function argument in the main program. C programmers are
SH> accustomed to using a "&" but that has different meanings in perl.
SH> To receive a scalar by reference inside the function
SH> implementation, you use an additional "$". So everywhere you have
SH> "$val" you would put "$$val". C programmers would put an extra "*"
SH> in front but that also has a different meaning in Perl.
What's important to reinforce is the distinction between "the value"
and "where the value is stored". In C you have memory and pointers to
memory; in Perl you have things and references to things. In Java you
have either both or neither, depending on how you count: there are
primitive types that you can't get a reference to, and everything else
is a reference type derived from Object).
SH> Actually all arguments are passed by reference in perl.
Hm, not strictly true. It's better to say that subroutine arguments,
in the absence of prototypes, are passed by "alias". As you point
out, assigning the value of an alias into a different variable does
not keep that special "alias"ness in the different variable.
SH> The reason your program is not working is that you made a copy of
SH> the original when you typed "my $val = pop @_". With the changes
SH> above, you will be making a copy of the reference, and not the
SH> original.
Be very careful and precise when you use the word "reference" in the
context of perl; it has a very specific meaning. And making a copy of
a reference is perfectly fine, and you can continue to access the
original object through the copy of the reference; to some extent,
that's the entire /point/ of references in Perl. They very much serve
the same role as pointers in C, and object references in Java.
E.g.:
| #!/usr/bin/perl
| # refs.plx
|
| use strict;
| use warnings;
|
| $\ = "\n";
|
| my $var = "hi"; print $var;
| my $ref1 = \$var;
| my $ref2 = $ref1;
| $$ref1 = "bye"; print $var;
Output:
| $ ./refs.plx
| hi
| bye
SH> So an alternative would be to say "$[0] = 'goodbye';". Nice
SH> transparent code, huh?
You meant to type $_[0], not $[0]. Which is even uglier. :)
This gives a quick sketch of what we've talked about so far:
| #!/usr/bin/perl
| # sub_args.plx
|
| use warnings;
| use strict;
|
| sub twiddle { $_[0] = "bar"; }
| sub useless { my $x = $_[0]; $x = "baz"; }
| sub use_ref { my $var_ref = $_[0]; $$var_ref = "quux"; }
|
| $\ = "\n";
|
| my $var = "foo"; print $var;
| twiddle( $var ); print $var;
| useless( $var ); print $var;
| use_ref( \$var ); print $var;
Output:
| $ ./sub_args.plx
| foo
| bar
| bar
| quux
SH> Beware: things get more complex when passing arrays as function
SH> arguments.
Yeah. Meditating over perlref, perllol, and perldsc are useful. A
modern perl book (Camel 3rd Ed, etc) is also helpful.
t.
More information about the LUG
mailing list