I'm sending a subroutine a hash, and fetching it with my($arg_ref) = @_;
But what exactly is %$arg_ref
? Is %$
dereferencing the hash?
-
$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.
chaos : Prototyping can be used to remove the reference-passing responsibility from the caller.Jon Ericson : 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.brian d foy : 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.Jon Ericson : 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.Schwern : @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. -
Instead of dereferencing the entire hash like that, you can grab individual items with
$arg_ref->{key}
-
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.) -
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.
-
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.
0 comments:
Post a Comment