tags:

views:

1614

answers:

5

I'm sending a subroutine a hash, and fetching it with my($arg_ref) = @_;

But what exactly is %$arg_ref? Is %$ dereferencing the hash?

+14  A: 

$arg_ref is a scalar since it uses the $ sigil. Presumably, it holds a hash reference. So yes, %$arg_ref deferences that hash reference. Another way to write it is %{$arg_ref}. This makes the intent of the code a bit more clear, though more verbose.

To quote from perldata(1):

 Scalar values are always named with '$', even when referring
 to a scalar that is part of an array or a hash.  The '$'
 symbol works semantically like the English word "the" in
 that it indicates a single value is expected.

     $days               # the simple scalar value "days"
     $days[28]           # the 29th element of array @days
     $days{'Feb'}        # the 'Feb' value from hash %days
     $#days              # the last index of array @days

So your example would be:

     %$arg_ref           # hash dereferenced from the value "arg_ref"

my($arg_ref) = @_; grabs the first item in the function's argument stack and places it in a local variable called $arg_ref. The caller is responsible for passing a hash reference. A more canonical way to write that is:

my $arg_ref = shift;

To create a hash reference you could start with a hash:

some_sub(\%hash);

Or you can create it with an anonymous hash reference:

some_sub({pi => 3.14, C => 4}); # Pi is a gross approximation.
Jon Ericson
Prototyping can be used to remove the reference-passing responsibility from the caller.
chaos
I don't think teaching prototyping the new Perl programmers is a good idea. It was a big barrier coming from C and Pascal. I needed to learn the true value of passing lists before prototypes made any sense to me. It might be handy here, however.
Jon Ericson
The $ sigil does not mean a scalar variable. It means a scalar *value*, as in $hash{key} and $array[$num]. In this case it's a scalar variable because it's a scalar value and there is no indexing chars after it.
brian d foy
I don't think I said $ indicated a variable of any sort. But I went ahead and added quote from perldata that draws out the meaning of the $ sigil.
Jon Ericson
@chaos Perl prototyping bad. Avoid! Flee! Not only is it difficult to use and loaded with traps, but the user thinks they're passing a copy to a subroutine when they're really passing a reference which the routine might modify.
Schwern
+6  A: 

Instead of dereferencing the entire hash like that, you can grab individual items with

$arg_ref->{key}
Paul Tomblin
+4  A: 

A good brief introduction to references (creating them and using them) in Perl is perldoc perfeftut. You can also read it online (or get it as a pdf). (It talks more about references in complex data structures than in terms of passing in and out of subroutines, but the syntax is the same.)

Telemachus
+1  A: 

Since it's somewhat clear this construct is being used to provide a hash reference as a list of named arguments to a sub it should also be noted that this

sub foo {
  my ($arg_ref) = @_;
  # do something with $arg_ref->{keys}
}

may be overkill as opposed to just unpacking @_

sub bar {
  my ($a, $b, $c) = @_;
  return $c / ( $a * $b );
}

Depending on how complex the argument list is.

mnology
+2  A: 
my %hash = ( fred => 'wilma',
             barney => 'betty');
my $hashref = \%hash;
my $freds_wife = $hashref->{fred};
my %hash_copy = %$hash # or %{$hash} as noted above.

Soo, what's the point of the syntax flexibility? Let's try this:

my %flintstones = ( fred => { wife => 'wilma',
                              kids => ['pebbles'],
                              pets => ['dino'],
                            }
                    barney => { # etc ... }
                  );

Actually for deep data structures like this it's often more convenient to start with a ref:

my $flintstones = { fred => { wife => 'Wilma',
                               kids => ['Pebbles'],
                               pets => ['Dino'],
                              },
                   };

OK, so fred gets a new pet, 'Velociraptor'

push @{$flintstones->{fred}->{pets}}, 'Velociraptor';

How many pets does Fred have?

scalar @ {flintstones->{fred}->{pets} }

Let's feed them ...

for my $pet ( @ {flintstones->{fred}->{pets} } ) {
    feed($pet)
}

and so on. The curly-bracket soup can look a bit daunting at first, but it becomes quite easy to deal with them in the end, so long as you're consistent in the way that you deal with them.

singingfish