Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

RFC (possible new tutorial) Guide to references; The Basics

by stevieb (Hermit)
on May 21, 2012 at 21:28 UTC ( #971693=perlmeditation: print w/ replies, xml ) Need Help??

Note: This is actually part one in a five part series, so if this goes over well, I can either append the other five parts or create them separately.

Understanding references and their subtleties in Perl is one of the more difficult concepts to fully wrap one's head around. However, once they are fully understood by the blossoming developer, they find a whole new level of capability and power to exploit and explore.

I often see newer programmers struggle with the concept of references on the Perl help sites I frequent. Some still have a ways to go, but many are at the stage where perhaps one more tutorial may push them over the edge and give them that 'Ahhhh' moment of clarity. My moment of clarity came when I read Randal Schwartz's "Learning Perl Objects, References & Modules" book for the something like the 8th time. Although once the concept of references is understood, the syntax and use cases can still be confusing for quite some time, especially in Perl, because There Is More Than One Way To Do It.

This tutorial will teach you the basics of Perl references, paving the way for more advanced aspects of their use.

This tutorial assumes that you have a very good understanding of the Perl variable types, when they are needed, and how they are used. Some exposure to references may also prove helpful, but shouldn't be required.

THE BASICS

References in Perl are nothing more than a scalar variable that instead of containing a usable value, they 'point' to a different variable. When you perform an action on a reference, you are actually performing the action on the variable that the reference points to. A Perl reference is similar to a shortcut to a file or program on your computer. When you double click the shortcut, the shortcut doesn't open, it's the file that the shortcut points to that does.

We'll start with arrays, and I'll get right into the code.

We'll define an array as normal, and then print out its contents.

my @array = ( 1, 2, 3 ); for my $elem ( @array ){ say $elem; }

Prepending the array with a backslash is how we take a reference to the array and assign the reference to a scalar. The scalar $aref now is a reference that points to @array.

my $aref = \@array;

At this point, if you tried to print out the contents of $aref, you would get the location of the array being pointed to. You know you have a reference if you ever try to print a scalar and you get output like the following:

ARRAY(0x9bfa8c8)

Before we can use the array the reference points to, we must dereference the reference. To gain access to the array and use it as normal, we use the array dereference operator @{}. Put the array reference inside of the dereference braces and we can use the reference just as if it was the array itself:

for my $elem ( @{ $aref } ){ say $elem; }

The standard way of assigning an individual array element to a scalar:

my $x = $array[0];

To access individual elements of the array through the reference, we use a different dereference operator:

my $y = $aref->[1];

Assign a string to the second element of the array in traditional fashion:

$array[1] = "assigning to array element 2";

To do the same thing through an array reference, we dereference it the same way we did when we were taking an element from the array through the reference:

$aref->[1] = "assigning to array element 2";

You just learnt how take a reference to an array (by prepending the array with a backslash), how to dereference the entire array reference by inserting the reference within the dereference block @{}, and how to dereference individual elements of the array through the reference with the -> dereference operator. That is all there is to it. Hashes are extremely similar. Let's look at them now.

Create and initialize a normal hash, and iterate over its contents:

my %hash = ( a => 1, b => 2, c => 3 ); while ( my ( $key, $value ) = each %hash ){ say "key: $key, value: $value"; }

Take a reference to the hash, and assign it to a scalar variable:

my $href = \%hash;

Now we'll iterate over the hash through the reference. To access the hash, we must dereference it just like we did the array reference above. The dereference operator for a hash reference is %{}. Again, just wrap the reference within its dereferencing block:

while ( my ( $key, $value ) = each %{ $href } ){ say "key: $key, value: $value"; }

Access an individual hash value:

my $x = $hash{ a };

Access an individual hash value through the reference. The dereference operator for accessing individual elements of a hash through a reference is the same one we used for an array (->).

my $y = $href->{ a };

Assign a value to hash key 'a':

$hash{ a } = "assigning to hash key a";

Assign a value to hash key 'a' through the reference:

$href->{ a } = "assigning to hash key a";

That's essentially the basics of taking a reference to something, and then dereferencing the reference to access the data it points to.

When we operate on a reference, we are essentially operating on the item being pointed to directly. Here is an example that shows, in action, how operating directly on the item has the same effect as operating on the item through the reference.

my @array = ( 1, 2, 3 ); my $aref = \@array; # assign a new value to $b[0] through the reference $aref->[0] = 99; # print the array for my $elem ( @array ){ say $elem; }

Output:

99 2 3

As you can see, the following two lines are equivalent:

$array[0] = 99; $aref->[0] = 99;

CHEAT SHEET

Here's a little cheat sheet for review before we move on to the next part in the series.

my @array = ( 1, 2, 3 ); my %hash = ( a => 1, b => 2, c => 3 ); # take a reference to the array my $aref = \@array; # take a reference to the hash my $href = \%hash; # access the entire array through its reference my $elem_count = scalar @{ $aref }; # access the entire hash through its reference my $keys_count = keys %{ $href }; # get a single element through the array reference my $element = $aref->[0]; # get a single value through the hash reference my $value = $href->{ a }; # assign to a single array element through its reference $aref->[0] = 1; # assign a value to a single hash key through its ref $href->{ a } = 1;

if you want to see where I'm going with this and you feel it ok as a tutorial, you can find the other parts of this series here that I would somehow blend in.

Comment on RFC (possible new tutorial) Guide to references; The Basics
Select or Download Code
Re: RFC (possible new tutorial) Guide to references; The Basics
by zentara (Archbishop) on May 22, 2012 at 11:22 UTC
    Your tutorial is easy to understand, that is good for someone trying to learn without having much Perl in their background. The one thing I thought of, which may cause a problem for beginners, is your use of @a for the example array. It's a minor nitpick, but it lends itself to the use of $a in the dereferencing, and that can make beginners erroneously think $a is a good choice as a variable in code. Of course, it's not $a in scalar context, but beginners usually don't know that.

    Oh well, maybe hitting the $a and $b glitch with sort is just one of the rights of passage of every Perl programmer. Maybe you could just mention the $a $b sort conflict, so when new Perl programmers read your tutorial, they will be aware. Or, use @ar for examples?


    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: RFC (possible new tutorial) Guide to references; The Basics
by Neighbour (Friar) on May 22, 2012 at 11:26 UTC
    It would help if you keep the cheat sheet strict :)
Re: RFC (possible new tutorial) Guide to references; The Basics
by stevieb (Hermit) on May 22, 2012 at 23:55 UTC

    Thanks zentara and Neighbour for the feedback.

    I took your advice, and changed the @a/@b to full names, and also fixed the cheat sheet code. How I broke that I don't know :)

    Cheers!

    Steve

Re: RFC (possible new tutorial) Guide to references; The Basics
by raybies (Chaplain) on May 25, 2012 at 14:03 UTC

    I think these two examples in your cheat sheet ending might be seen as confusing in that the values are assigned to scalars and force scalar context, which ultimately is not what the comment is claiming above the program statements.

    # access the entire array through its reference my $elem_count = scalar @{ $aref }; # access the entire hash through its reference my $keys_count = keys %{ $href };

    I get the point that the %{} and @{} make the hash reference into regular hash context, and the array reference into array context, but the final result in the examples in both are actually scalars, so the end result is the number of array elements, and the number of keys of the hash that's referred to by the variable. Perhaps that's a bit complex for a simple cheat example. Dunno, or you might want to clarify the comment to reflect the end result.

    Of course the names of the variables is a good choice, but I don't know if that's sufficient.

Re: RFC (possible new tutorial) Guide to references; The Basics
by nightgoat (Acolyte) on May 25, 2012 at 17:03 UTC
    Thanks for posting this! I was on PerlMonks looking for some info on references, and as I tend to do, I started browsing the meditations. It paid off!
Re: RFC (possible new tutorial) Guide to references; The Basics
by Don Coyote (Monk) on Jun 13, 2012 at 09:24 UTC

    Yes StevieB I think you have hit the nail on the head. I do understand data types enough to know what you are talking about and yes, I do need the one more simple tutuorial to 'get' the accessing of referenced data tyes. probably a few more.

    In some live code I am continually updating I have been getting confused a lot around the use of the dereferencing symbol '->' especially as it seems to have many uses between hashes and subs in regards to methods and classes.

    There was a brief discussion about the importer being still broken, and I don't know but maybe this is why I am able to call methods as classes when i shouldn't or vice-versa or something if that is what im doing. Basically if i hack it and it works im good, but I kind of expect the main functionalities of inheritance to be right firstly. hmmm. of course i know not what im talking about here. and secondly to 'fix' that now will break pretty much all of cpan?

    some perl teachings/implementations seem to contradict how you are 'allowed' to import and/or call methods/classes from modules. For example - iirc, i should say use cgi qw/:comment/ but because i have declared the single import that should define all other methods as not imported. And that I should then only be able to access object classes using class calls and not method calls etc......

    So yeah! Can't wait for the objects tuts. Thanks Greatly, and please continue.


    Coyote
    "Auto-decrement is not magical."
    programming perl rev 1

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://971693]
Approved by ww
Front-paged by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (15)
As of 2014-10-24 15:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (132 votes), past polls