w3b has asked for the wisdom of the Perl Monks concerning the following question:
Hi, monks!
I read about references and... i have question:
Why use references?
I can write :
$int = '2'; $int2 = $int;
but i can use references and write:
$int = '2'; $int2 = \$int;
So what differences??
Re: Why use references?
by g0n (Priest) on Dec 11, 2005 at 19:25 UTC
|
Leading on from jdporter & chas' answers:
1) because you may want to pass a scalar, a list and a hash to a subroutine. You can do that with:
testfunc($scalar,\@array,\%hash);
sub testfunc
{
my ($scalar,$arrayref,$hashref) = @_;
}
2) Because hash references are fundamental to OO perl.
3) (Elaborating chas a little) Because a data structure like:
my $appointments = {
monday=> { "10:30"=>"dentist",
"11:30"=>"doctor" },
tuesday => { "10:30" => " planning meeting",
"16:30" => " funding deadline" }
};
can be very useful.
4) Because once you start using array refs and hash refs, you'lll wonder how you ever managed without them.
I may be missing something, but I rarely have occasion to use a scalar ref in the simple $ref = \$var; form.
Update:Struck out 'hash' in 'hash references' at blazars suggestion - TIMTOWTDI.
--------------------------------------------------------------
"If there is such a phenomenon as absolute evil, it consists in treating another human being as a thing."
John Brunner, "The Shockwave Rider".
| [reply] [d/l] [select] |
|
Because hash references are fundamental to OO perl.
s/hash//;
| [reply] [d/l] |
|
| [reply] |
Re: Why use references?
by chas (Priest) on Dec 11, 2005 at 19:04 UTC
|
Of course, read the docs. However, here's a very short answer.
1. To model muldimensional arrays, (hashes, etc.) An element of an array must be a scalar, so it can't be another array - but it can be a reference to an array.
2. It is usual more economical to pass an array (or hash) reference to a sub (and dereference as needed inside the
sub) rather than passing the whole array (or hash.) And when
passing several arrays (or hashes) to a sub, they get flattened into a single list and lose their integrity; but you can pass several array or hash references to a sub and then dereference inside the sub.
Of course, the language could have been designed so that
references only appear behind the scenes and aren't handled
by the user, but then likely a lot of flexibility would have been lost. | [reply] |
Re: Why use references?
by jdporter (Paladin) on Dec 11, 2005 at 18:19 UTC
|
| [reply] |
Re: Why use references?
by ysth (Canon) on Dec 11, 2005 at 19:54 UTC
|
I think you'll need to run into a problem to which references are the answer before grasping the reason. That said, reviewing some of the suggested documentation now may help you identify when you reach that point. | [reply] |
Re: Why use references?
by jhourcle (Prior) on Dec 12, 2005 at 03:33 UTC
|
Most of the responses concern themselves with references to arrays and hashes, except for pileofrogs who deals with scalar references in the context of passing arguments to procedures, but I don't know that it really explained what the advantage was.
These days, you can't assume that someone has already had C, and had already wrapped their head around pointers -- basically, in the example you gave, $int2 contains the location in memory to $int ... which allows us to modify the original variable, even when the original isn't in scope to be modified:
Now, with something that simple, you can just return it from the function, and Perl allows you to easily return more than one item from a function, but for some people, this style just makes more sense.
For other times, we can use the reference as an alias to a value that we want to track, but we still want the variable to keep its original identity:
These are rather simplistic examples, and don't really show the full power of what you can do with scalar references. As you're starting out in programming, you'll probably never need to use them -- in fact, until you start to use them, and start thinking about where they'll save you time and effort, they're probably more pain than they're worth as you get confused and try to assign values directly to the reference, and have to track down your errors.
| [reply] [d/l] [select] |
Re: Why use references?
by astaines (Curate) on Dec 12, 2005 at 00:58 UTC
|
| [reply] |
Re: Why use references?
by talexb (Chancellor) on Dec 12, 2005 at 00:52 UTC
|
If you have any idea about a standard transmission (one where you choose what gear to be in, different from an automatic transmission which chooses for you), then programming without references (or pointers, depending on your vocabulary) is like driving everywhere in first gear. The acceleration's great, but you don't move very fast.
Alex / talexb / Toronto
"Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds
| [reply] |
Re: Why use references?
by pileofrogs (Priest) on Dec 12, 2005 at 01:02 UTC
|
You also might want to modify an arg to a subrutine. E.G.
With References
sub increment {
my $arg_ref = shift;
$$arg_ref++;
if (is_bad($$arg_ref)) {
return "FAILURE!";
}
return undef;
}
my $num = 0;
my $err;
$err = increment(\$num);
if ($err) {
die $err;
}
print "$num\n";
|
Without References
sub increment {
my $arg = shift
if (is_bad($arg)) {
die "FAILURE";
}
return ++$arg;
}
my $num = 0;
$num = increment($num);
print "$num\n";
|
I don't think my sub that uses references is any better than the
one that doesn't. It just shows two ways of doing the same thing.
Because you pass $num as a reference, the subrutine can change num.
Then you can use the function's return for something else.
Update: chas! I've fixed the example to use ++$arg rather than $arg++.
AND! Woah. Baked my noodle with that one. So the only reason I've been convinced that subrutine args were passed as values was because I was using shift all the time!? Man... aye aye aye... | [reply] [d/l] [select] |
|
In your "Without References" example, don't you need
return ++$arg;?
(and a semicolon after shift?)
Also, consider the following:
sub increment {
++$_[0];
}
$num=0;
increment($num);
print $num,"\n";
which shows that args are passed "by reference" by default.
Of course, it may not be good style to alter @_ in this way, but the point is that you don't need to pass a reference to alter the argument inside the sub.
(Updated to make less confusing.) | [reply] [d/l] [select] |
Re: Why use references?
by edgreenberg (Acolyte) on Dec 12, 2005 at 02:41 UTC
|
I frequently return references to arrays and hashes from subroutines so that I can return undef if things fail.
| [reply] |
|
Playing devil's advocate, what about arrays and hashes prevents you from returning undef on failure?
thor
The only easy day was yesterday
| [reply] |
|
@a = foo(); sub foo { return(undef); }
makes @a contain a single undef value. How do you know that's supposed to be an error, rather than a non-error single undef?
Furthermore, in
%h = foo(); sub foo { return(undef); }
you get an Odd number of elements in hash assignment warning.
Even if you fix/ignore that, how do you know the sub didn't mean to return a (non-error) ( "" => undef ) list?
If one chooses to use a return value of undef to signify errors, it makes sense to return references for non-error conditions — even for scalars.
Personally, I try to let any false value indicate failure. This would include undef/''/0
for scalar returns, and empty lists for arrays/hashes.
This hash the "advantage" of being consistent with many of the built-in functions.
But when I need more power (which is usually), I throw exceptions for errors and make the assumption
that a function call returning means success.
eval {
my @a = foo();
# if I'm here, then foo() succeeded. at least, it didn't throw an
+error.
};
Another thing you sometimes see people do is return data via OUT parameters, and let
the function return value only indicate success/failure.
We're building the house of the future together.
| [reply] [d/l] [select] |
|
|