ACCC Home Page ACADEMIC COMPUTING and COMMUNICATIONS CENTER
Accounts / Passwords Email Labs / Classrooms Telecom Software Computing and Network Services Education / Teaching Getting Help
 
Seminar - Perl II
0. Contents 1. Intro 2. Sources 3. References 4. Packages 5. Classes
6. Ties & DBM 7. Typeglobs 8. CGI 9. Security 10. Example  

References

   
 
     
Soft References
 

Suppose you don't know the name of a variable till runtime. With soft references, you can construct the variable on the fly.

    $pizza      = "onion";    # normal variable
    $topping    = "pizza";
    ${$topping} = "onion";    # soft reference
    $$topping   = "onion";    # soft reference

Sometimes soft references are quite useful. But they can also hide subtle bugs, so some people like to avoid them. You may have a construct like ${expression} where expression evaluates to a string. If you make a mistake, and it evaluates to the wrong string, perl will merrily create a new variable for you.

Another problem is that syntactically, soft and hard references look nearly the same. $$topping refers to a hard reference if $topping is a hard reference, and to a soft reference if it is a plain string. So again, when you are mixing references, typos can become valid perl and are hard to spot.

Soft references are not as efficient as normal variables. Also, they cannot work with my() variables, only global or local variables.

    my $pizza;
    ${pizza}   = "sausage";  # normal usage
    ${"pizza"} = "mushroom"; # soft reference
    print $pizza;	     #  sausage
    print $::pizza;	     #  mushroom
 
     
Hard References
 

A hard reference (often just called "reference") is really a pointer. You can't do pointer arithmetic, but you can create and dereference them.

Perl manages all the memory allocation, and it also keeps track of the kind of variable pointed to. You can't create a reference to an array and then dereference it as if it were a scalar. So perl references are much safer than C pointers.

A reference is a scalar, just like a string or number. Of course, perl knows the difference internally. You can't tell the difference just by looking, but you can use the ref() function if you need to.

If you have a named variable, take the reference by putting a backslash in front.

 $r = \$s;        # reference to a scalar
 $r = \@a;        # reference to an array
 $r = \%h;        # reference to a hash
 $r = \$h{a};     # reference to a single hash value
 $r = \&mysub;    # reference to a subroutine
 $r = \mysub();   # reference to what was returned
 $rr = \$r;       # reference to a reference
 $r = \($a, $b);  # Surprise!  Probably wrong.
                  # \($a, $b) means (\$a, \$b)
 
     
Dereferencing Notations
 

Dereferencing is the tricky part. A crucial point is that you must be aware of the kind of reference you are dereferencing.

On the whole, you can enclose the reference in braces, and put a $,@ or % sign in front, depending on if you are dereferencing a scalar, array, or hash.

 $r = \$s;
 $a = ${$r};     # $a has the value of $s
 $a = $$r;       # $a has the value of $s

 $r = \@a;
 @b = @{$r};     # @b has the value of @a
 @b = @$r;       # @b has the value of @a

 $r = \%h;
 %c = %{$r};     # %c has the value of %ha
 %c = %$r;       # %c has the value of %ha

 $r = \&mysub;
 $&mysub();      # call the subroutine
In lots of cases, you can omit the braces. This can help when you have references to references. But when ambiguous, you must use the braces.

So far, so good. But suppose you have a hashref or arrayref, and you want to do something with a single element? There's more than one way to do it.

 $ar = \@a;
 @{$ar}[0]     # first element
 @$ar[0]       # first element; this is NOT @{$ar[0]}
 $ar->[0]      # also first element

Yes, perl uses the arrow notation to find an element of an arrayref, kinda like C does with structure pointers. And with perl, $hr->{key} also works with hash references.

Now suppose each array element contains an arrayref. (This is starting to sound like multidimensional arrays!)

 @a[0] = \@a0;
 @a[1] = \@a1;
 @a[2] = \@a2;
 $ar   = \@a;
 $a[0]->[0]     # first element of @a0
 $a[0][0]       # first element of @a0
 $ar->[0]->[0]  # first element of @a0
 $ar->[0][0]    # first element of @a0

That's right, @a is an array of arrayrefs. We can use the arrow notation, in addition to the braces (if necessary) to dereference this. Note that the arrow in between subscript brackets can be dropped. So that $a[0][0] sure looks like a multidimentional array. But in perl, we can mix hashrefs and arrayrefs, to get constructs like $a[0]{stuff}[2].

 
     
Anonymous References
 

You don't have to name an array or hash in order to create an arrayref or hashref. In the above example, although @a was an array of arrayrefs, each of the arrayrefs had an explicit name. This is awkward when you don't need all those subsidiary names. Just use [(list)] to create an anonymous arrayref, and {(list)} to create an anonymous hashref.

 $h{july4} = ["salmon", "peas"];
 $h{xmas}  = ["turkey", "stuffing"];
Therefore %h is a hash whose values are arrayrefs. This notation is often done like this:
 %h = (
      july4 => ["salmon", "peas"],
      xmax  => ["turkey", "stuffing],
 );
 
 print $h{xmas}[0];     # prints turkey

Note is is possible to put a named array inside [] or {} to create an annonymous arrayref or hashref. In such cases, a copy of the named array is made and put in the anonyous reference.

  @a = (1..10);
  $b = [@a];
  foreach $e ( @$b ) {
    $e = 0;
  }
  print "$a[0] $b->[0]";    # prints  1 0
 
     
Data Structures
 

Perl doesn't do multidimensional arrays directly. But since an array value or a hash value can be a reference, you can in practice deal with arrays of hashes of subroutines of ...

See the books for details. But in many cases, these data structures can spring to life.

 $x[2][3] = 1;   # Create @x, and create anon [] in $x[2]
 
 

Perl II Previous: 2. Sources Next: 4. Packages


1999-3-3  BobG
UIC Home Page Search UIC Pages Contact UIC