in reply to Re: Trying to learn about References
in thread Trying to learn about References

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

Replies are listed 'Best First'.
Re: Trying to learn about References
by Dominus (Parson) on Jan 06, 2002 at 21:16 UTC
    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

      Certainly I agree with what you said. Thanks for your comments ;-). Probably, what I _really_ meant is doing something like
      my ($in) = @_;
      will initialize a new variable $in with the contents of the first argument.. and if it's other than a reference the cost of doing so may be high if the data to be thus 'copied' is substantial.

      I've done a bit more playing with Devel::Peek module which allows one to look inside the Perl variables (look up their guts sort of ;-):
      #!/usr/local/bin/perl use Devel::Peek 'Dump'; sub foo { # this will create a new variable $s and copy first argument's con +tents right? my ($s) = @_; print "Dump inside trim():\n"; print "\$_[0] (this one is infact a 'synonym' to the actual variab +le; not it's copy :-) :\n"; Dump($_[0]);print"\n"; print "\$s (this is a copy of the 1-st argument:\n"; Dump($s);print"\n"; } sub bar(\$) { # this will create a new variable $s and copy first argument's con +tents as well, # however, it's much faster here compred to foo() since in this ca +se only # a reference to the actual variable is copied, not the actual var +iable's # contents. my ($s) = @_; print "Dump inside bar(\\\$):\n"; print "\$_[0]:\n"; Dump($_[0]);print"\n"; print "\$s (this is a copy of the 1-st argument, which is nothing +more but a reference..):\n"; Dump($s);print"\n"; } $s = "some text here "; print "Dump before:\n"; Dump($s);print"\n"; foo($s); bar($s); print "Dump after:\n"; Dump($s);print"\n";
      And here's the output produced by this script:
      Dump before: SV = PV(0xf0c44) at 0xfe99c REFCNT = 1 FLAGS = (POK,pPOK) PV = 0xf7560 "some text here "\0 CUR = 15 LEN = 16 Dump inside trim(): $_[0] (this one is infact a 'synonym' to the actual variable; not it's + copy :-) : SV = PV(0xf0c44) at 0xfe99c REFCNT = 1 FLAGS = (POK,pPOK) PV = 0xf7560 "some text here "\0 CUR = 15 LEN = 16 $s (this is a copy of the 1-st argument: SV = PV(0xf0c98) at 0xfe9c0 REFCNT = 1 FLAGS = (PADBUSY,PADMY,POK,pPOK) PV = 0xf7540 "some text here "\0 CUR = 15 LEN = 16 Dump inside bar(\$): $_[0]: SV = RV(0x11581c) at 0xf096c REFCNT = 1 FLAGS = (ROK) RV = 0xfe99c SV = PV(0xf0c44) at 0xfe99c REFCNT = 3 FLAGS = (POK,pPOK) PV = 0xf7560 "some text here "\0 CUR = 15 LEN = 16 $s (this is a copy of the 1-st argument, which is nothing more but a r +eference..): SV = RV(0x115828) at 0x1164b0 REFCNT = 1 FLAGS = (PADBUSY,PADMY,ROK) RV = 0xfe99c SV = PV(0xf0c44) at 0xfe99c REFCNT = 3 FLAGS = (POK,pPOK) PV = 0xf7560 "some text here "\0 CUR = 15 LEN = 16 Dump after: SV = PV(0xf0c44) at 0xfe99c REFCNT = 1 FLAGS = (POK,pPOK) PV = 0xf7560 "some text here "\0 CUR = 15 LEN = 16
      Certainly, the difference is subtle. And, also, '$_[0]' itself is not a copy of the source variable, but rather it's 'synonym' or reference (c-like). However, most of the time it's much easier to simply pass around references just in case, at least that's how me thinks ;-)...

      "There is no system but GNU, and Linux is one of its kernels." -- Confession of Faith