http://www.perlmonks.org?node_id=155853

DigitalKitty has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks.

I was wondering about the benefit of passing one or more references to a sub.

#!/usr/bin/perl -w use strict; my $num = 20; my @array = ( "Carolyn", "Aimee", "Bob", "Janice" ); &PrintData(\$num, \@array); sub PrintData { my ($value) = @_; print "The value of \$num is: ${$value}"; }


If I dereference the data stored in the private scalar $value, I will see 20 printed to STDOUT. Without that, I can interpolate the value as if it were not in a sub at all. Can I assign more than one sub parameter to a private var ( each individualized )? Since I am still learning, I am trying to understand what references are used for exactly. Does one have to assign the address to a private var? If not, then what is the point?

Thanks in advance,

-DK.

Replies are listed 'Best First'.
Re: Passing references to a sub.
by Juerd (Abbot) on Apr 01, 2002 at 21:06 UTC

    If not, then what is the point [of references]?

    References are created so you can put ANYTHING in a scalar. This is very handy, as array elements, list elements and hash values can only be scalars. It's also handy to be able to point to an array when calling a sub, instead of passing the entire array.

    Imagine you want a two-dimensional array - without references, it would not be possible: you can't have an array as an array element (it would be flattened in the array assignment). Fortunately, you can fit an array in a scalar using a reference, and that way you can have multi-dimensional array.

    Imagine you have a machine with a gigabyte of available memory, and a single scalar that uses 600 megabytes of it. If you would pass it to a sub, and it would be copied, you'd run out of memory. Fortunately, by using a reference you can just point to it, and pass only a few bytes. The reference can be copied, but it will still point to the same data.

    Please do read perlreftut and perlref. (Yeah, I know the perlreftut link is broken. Will someone PLEASE update the on-site documentation? Until then, use perldoc perlreftut)

    U28geW91IGNhbiBhbGwgcm90MTMgY
    W5kIHBhY2soKS4gQnV0IGRvIHlvdS
    ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
    geW91IHNlZSBpdD8gIC0tIEp1ZXJk
    

Re: Passing references to a sub.
by the_slycer (Chaplain) on Apr 01, 2002 at 21:42 UTC
    The other use of references is when you need to pass two arrays (or a hash and an array) into a sub.
    Consider:
    my @array1 = ("foo", "foo1", "foo2"); my @array2 = ("bar", "bar1", "bar2"); print_data(@array1, @array2); sub print_data { @array1 = @_; #array1 gets all of @_ @array2 = @_; #array2 also gets all of @_ }
    vs
    print_data(\@array1, \@array2); sub print_data { my @data1 = @{$_[0]}; #dereferences first array into @data1 my @data2 = @{$_[1]}; #dereferences second array into @data2 }
    The second version is more often than not what you actually want.
Re: Passing references to a sub.
by perrin (Chancellor) on Apr 01, 2002 at 21:26 UTC
    There are a couple of things going on here. The first is the question of why you should pass variables to a sub instead of using globals, or lexicals that are in the same scope as the sub. The answer is simply that it's easier to see what's going on. The passing of the variable -- and the acceptance of the variable in the sub by reading @_ -- is a kind of documentation, showing what that sub expects. This is standard programming technique stuff. (There's also an issue of creating closures, but that's a little more information than you need right now.)

    The other part is whether or not you should pass references. You probably shouldn't when passing scalars, unless they're huge, but all other types are safer and more efficient when passed as references. See the various documentation sources on references for more explanation on that.

Re: Passing references to a sub.
by shotgunefx (Parson) on Apr 02, 2002 at 08:14 UTC
    One thing I'd like to add to juerds post is that if you pass a reference and modify it in the sub, you will in fact be modifying the actual data structure (hence reference). This may not be what you want to do. It's not a problem if you are aware of it.
    #!/usr/bin/perl -w use strict; my @array = (1..10); print join(", ",@array),"\n"; sillyfunc(\@array); print join(", ",@array),"\n"; sub sillyfunc{ my $aref = shift; # multiply each element by itself. $_ *= $_ foreach @{$aref}; } __END__ Even if you don't want to modify the original data, refs are used to avoid flattening. @array1=(1,2,3); @array2=('a','b','c'); (@array1,@array2) flattened would equal (1,2,3,a,b,c); What elements belong to which array?


    So in our sillyfunc, if we didn't want to actually modify the original data structure, but still wanted to pass by reference, you could make a shallow copy of the original by changing the $aref assignment to my $aref = [ @{$_[0]} ] which basically says take data referent in $_[0] and put it in a new anonymous array and stuff a reference to it in $aref.

    This is fine for simple data structures, but be aware that if the ref the data structure is referencing contains more references, the original and the copy's element references will still be referencing the same things. That's why it's called a shallow copy. It only gives you a new copy of the top layer.

    I hope I haven't made this sound more confusing than it is. I've referenced references 9 times here...
    Let me know if you need me to clarify anything and hope this helps.

    -Lee

    "To be civilized is to deny one's nature."
Re: Passing references to a sub.
by physi (Friar) on Apr 02, 2002 at 07:30 UTC
    A very nice lesson about references is this one from busunsl
    ----------------------------------- --the good, the bad and the physi-- -----------------------------------
Re: Passing references to a sub.
by data64 (Chaplain) on Apr 02, 2002 at 14:45 UTC

    You might also want to look at Understanding References


    <cite>Just a tongue-tied, twisted, earth-bound misfit. -- Pink Floyd</cite>