Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Trying to learn about References

by dru145 (Friar)
on Jan 04, 2002 at 20:12 UTC ( [id://136290]=perlmeditation: print w/replies, xml ) Need Help??

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.

Replies are listed 'Best First'.
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

      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.
      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
        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

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.

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.

      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.

      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.
(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)
    
Re: Trying to learn about References
by coolmichael (Deacon) on Jan 05, 2002 at 11:24 UTC
    Other monks here have already answered your questions, but I thought it might help to point out this quick reference by our very own tye. It doesn't answer your specific questions, but it is very helpful for the syntax.

    I had a very hard time with references until I found it.

    Michael.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://136290]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (None)
    As of 2024-04-25 03:54 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      No recent polls found