Good Day Fellow Monks,
I desired to enlighten myself today and attempted to read perlref to little avail. I'm quite confused with references. When should you use them? Why would you use them? One reason that I got out of it is when you have a complex hash or an array within an array, but what are some other reason? I appreciate if someone would try to explain this to me in lamen terms, maybe with a few basic examples.
Thanks,
Dru
Another satisfied monk.
Re: Trying to learn about References
by davorg (Chancellor) on Jan 04, 2002 at 20:24 UTC
|
As you say, one good reason for references is to build
complex data structures. Another is to pass arrays and
hashes into and out of subroutines. And, of course, all
of Perl's OO capability is based on references.
Many people find perlref to be a bit dry
on first reading. That's why Dominus wrote perlreftut. You might find that makes a bit more sense to you.
--
<http://www.dave.org.uk>
"The first rule of Perl club is you do not talk about
Perl club." -- Chip Salzenberg
| [reply] |
|
Thanks for the suggestion Dave. I actually went through my perl library and found a very good explanation on refernces in Elements of Programming Perl and it started sinking in.
Dru
Another satisfied monk.
| [reply] |
|
Another good use for references is to avoid making 'copies'
of data that is being passed to a sub in the arguments
list (you simply pass addresses to given variables so that
you may use those addresses -- references -- inside the sub
to access original variable values). Passing references to
original variables may also prove useful when you see a need
in modifying the original variable inside a subroutine.
Here's a pretty basic exaple:
sub by_val {
my ($foo) = @_;
print "Foo = $foo\n";
$foo = 10; # only 'foo' belonging to this sub is modifi
+ed
}
sub by_ref {
my ($foo_ref) = @_;
print "Foo = $$foo_ref\n"; # pring value in 'bar'
$$foo_ref = 10; # will modify 'bar'
}
my $bar = 5;
by_val($bar);
print "bar = $bar\n";
by_ref(\$bar); # $bar may no be modified inside the sub.
print "bar = $bar\n";
I'm also a fan of using references when passing large chunks
of text (string variables) around to be used in various
subroutines. This again boils down to not having to copy
contents of a variable.
"There is no system but GNU, and Linux is one of its kernels." -- Confession of Faith
|
| [reply] [d/l] |
|
A lot of what you said isn't correct. For example,
you said:
I'm also a fan of using references when passing large chunks of text (string variables)
around to be used in various subroutines. This again boils down to not having to copy
contents of a variable.
This is erroneous, because when you pass a string to a subroutine,
Perl does not copy the contents of the variable.
And you made the same mistake when you named one of your
example subroutines by_val. Perl does not pass
scalar data by value. Scalar data is always passed by reference,
whether you use an explicit reference or not.
Consider:
sub trim {
$_[0] =~ s/^\s+//;
$_[0] =~ s/\s+$//;
$_[0];
}
my $var = " I like pie. ";
trim($var);
print $var;
The call to the trim function actually modifies
$var, because scalar data is passed by reference,
not by value. The value of $var is not
copied.
The technique you suggest is more useful for arrays
and hashes. foo(@array) passes a (possibly long) list of
scalars to foo(), but foo(\@array)
passes only a single reference.
--
Mark Dominus
Perl Paraphernalia
| [reply] [d/l] |
|
Re: Trying to learn about References
by dragonchild (Archbishop) on Jan 04, 2002 at 21:14 UTC
|
Another reason to use references is to speed up your subroutine calls. Perl uses "pass by value", which actually copies stuff into @_. Not a big deal, unless you're passing a 10,000 element hash. So, you can do "pass by reference", which is simply one scalar. :-)
------ We are the carpenters and bricklayers of the Information Age. Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement. | [reply] |
Re: Trying to learn about References
by talexb (Chancellor) on Jan 04, 2002 at 21:36 UTC
|
Instead of giving you the theory, which is probably covered much better elwsewhere, let me give you a practical example of something I did rcently which put a smile on my face.
Once of the first modules I wrote did some simple manipulations with dates (this was in early 1999, before I knew what CPAN was all about). Since it does what I want and I know how it works, I pulled it off of a dusty shelf and cleaned up the code so I could re-use it for a project. The work I did included changing one subroutine call from
Adjust ( $Date, $DeltaYears, $DeltaMonths, $DeltaDays );
to use a hash for passing the parameters. Originally, if I wanted to call using only some of the parameters, I'd have to say
Adjust ( $Date, 0, 0, 15 ); # or
Adjust ( $Date, 0, -1, 0 ); # or
Adjust ( $Date, -3, 0, -1 );
Now I pass in an anonymous hash reference so that those examples become:
Adjust ( { date => $Date, day => 15 } ); # or
Adjust ( { date => $Date, month => -1 } ); # or
Adjust ( { date => $Date, year => -3, day => -1 } );
The great thing about this technique is that I only pass in the values I need to. If the values aren't there, the subroutine will assume some default value. How?
sub Adjust
{
my ( $Args ) = @_;
my $Year = $Args->{ year } || 0;
my $Month = $Args->{ month } || 0;
my $Day = $Args->{ day } || 0;
# More code ..
}
The double bar zero at the end of the three lines allows an undefined value to be interpreted as a zero -- this allows you to specify whatever default value you want, 5, 42, "U.S." or whatever.
Obviously, this becomes much cooler the more parameters you pass in -- and another great thing is that you can expand the subroutine's functionality without worrying about how it affects old code. In an old script I wrote, I had a subroutine that accepted a dozen or so parameters; adding a new one meant searching through the other scripts that called that script and updating all of them.
This technique is much easier to maintain; in my example, I would have had to set up a default value for the new parameter -- and I'd be done!
--t. alex
"Excellent. Release the hounds." -- Monty Burns.
| [reply] [d/l] [select] |
|
A warning to the reader -- what talexb has done using the ||= operator is valid and useful, but has a catch. It isn't truly a default-setting operator (see Perl 6's //= operator) but rather a "set me to the following value if my current value evaluates to false".
Note that any time a false value is a valid value for your variable, using the ||= to set the default will fail to produce the desired results.
| [reply] |
|
| [reply] |
|
The argument processing that you are doing here suffers
from the problem that if someone calls your function and
has a typo in their hash key, there is no check for it.
Also people cannot choose to explicitly use false values.
At the expense of considerable overhead, the approach I
describe at Re (tilly) 2: passing subroutine arguments directly into a hash solves both problems.
| [reply] |
(jeffa) Re: Trying to learn about References
by jeffa (Bishop) on Jan 04, 2002 at 23:19 UTC
|
Here is an easy one - pass two (or more)
arrays (or hashes) to a subroutine:
use strict;
my @a = (0..4);
my @b = ('a'..'e');
&foo(@a,@b);
&bar(\@a,\@b);
sub foo {
my (@a,@b) = @_;
print "a: ", join(',',@a), "\n";
print "b: ", join(',',@b), "\n";
}
sub bar {
my ($a,$b) = @_;
print "a: ", join(',',@$a), "\n";
print "b: ", join(',',@$b), "\n";
}
Subroutine foo() tries to pass two arrays, and as a result
they are 'squashed' into one array. Subroutine bar() passes
the two arrays by reference, and because it 'asks' for
references in this line:
my ($a,$b) = @_;
the arrays are not squashed. Maybe it would be clearer
if you understand that @_ is an array itself, from
perldata (with a paraphrase by me):
You can actually put an array or hash anywhere in the
list [subroutine arguments which are passed to @_],
but the first one in the list will soak up all the
values, and anything after it will become undefined.
Hence, in subroutine foo(), @a soaks up all of the elements
that were meant for @b.
jeffa
L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
F--F--F--F--F--F--F--F--
(the triplet paradiddle)
| [reply] [d/l] [select] |
Re: Trying to learn about References
by coolmichael (Deacon) on Jan 05, 2002 at 11:24 UTC
|
| [reply] |
|
|