I know $, @ and % are for declaring scalars, arrays and hashes. But I am confused when when $ is used in declaration of other things like
my %myhash1 = ( a => 1, b => 2 );
my $myhash2 = { A => 27, B => 27};
and usage of following syntax
%myhash1
%$myhash2
Can someone please explain me the difference and when to use them.
No, the sigils refer to the mode of access. $ means a single element, @ means multiple elements and % means key/value pairs. Demo:
$myhash1{a} # 1
@myhash1{qw(a b)} # (1, 2)
%myhash1{a} # (a => 1)
$$myhash2{A} # 27
@$myhash2{qw(A B)} # (27, 27)
%$myhash2{A} # (A => 27)
which is just short-hand for
${ $myhash2 }{A} # 27
@{ $myhash2 }{qw(A B)} # (27, 27)
%{ $myhash2 }{A} # (A => 27)
which is much more clearly written using the -> deref operator
$myhash2->{A} # 27
$myhash2->@{qw(A B)} # (27, 27)
$myhash2->%{A} # (A => 27)
Prefer the notation shown in the last block.
Lack of subscripting braces:
%myhash1 means: all k/v pairs in the hash.%$myhash2, %{ $myhash2 }, $myhash2->%* means: all k/v pairs in the dereferenced hash.Perl 5 sigils (the $, @, and %) can be confusing. Here's a condensed explanation. (The Perl 6 rules are different and I'm skipping them here, and as @ikegami notes, there are some other features, like hash and array slices, that I'm also skipping for concision.)
A dollar sign sigil always means "I am dealing with a scalar value". So the variable $foo is a variable containing a single scalar value (there are cases as noted where a scalars actually contains multiple different things that are accessed in different contexts, but this is not important for what we're interested in right now).
This is true when you're accessing array and hash elements: $foo[0] says "I am accessing the scalar value found in element 0 of the array @foo. For a hash, $foo{'bar'} says "I am accessing the scalar value found in the element whose key is bar in the hash %foo.
An at-sign sigil denotes an array as a whole. @foo means "all of the array whose name is foo". (Skipping slices here; they're a way to get a list of things out of a hash or array at once. Really useful, but they'll obscure our point right now.)
Similarly, a percent sign denotes a hash as a whole. %foo is the hash named foo -- all of it at once. (Same for hash slices.)
These are all the base data types in Perl: scalars ($), arrays (@), and hashes (%). There's also the sub (& - function) type, which we'll talk more about below, and globs (* - which are beyond the scope of this answer, so we'll skip them too).
If we want more complex, nested data structures, we now have to move on to references.
A reference is, to wildly oversimplify, essentially a pointer that knows the kind of thing it points to. References are always scalars. If we want a reference to something, there are, as one would expect in Perl 5, several ways to get one:
\) operator to specifically get a reference. We can do this with any of the three types of variables (scalar, hash, array) and with subroutines as well (remember, subroutines have a sigil of &). This is the only way to get a reference to a scalar variable.Here's examples of each:
# Define a reference to a scalar
$foo = \$bar;
# Define a reference to an array, a hash and an existing subroutine:
$x = \@w;
$y = \%zorch;
$z = \&do_stuff;
# define anonymous arrays, hashes, and subs:
$my_array = [2, 3, 'fred', 'hoplite'];
$my_hash = {foo => 'bar', baz => 'quux'};
$pi_sub = sub { return 3.14 };
There are three different ways to "dereference" (follow the pointer in) a reference.
Here are examples:
# Dereference a scalar using stacked sigils.
print $$foo; # $foo is a reference to the scalar $bar
# the second $ says "please give me the value of the scalar
$ I now have" (in this case that's $bar).
# Use braces and sigils to dereference a scalar, getting a hash/array
%hash = ( a => 1, b => 2);
my %thing = %{ $my_hash }; # dereference the scalar
# copy the resulting hash into %thing
# Chained dereferences
# A hash of hashes:
$sample = { one => { a => 1, b => 2}, two => { aa => 4, bb => 8 }};
# To get to 8, we need to dereference twice:
$eight = $sample->{two}->{bb};
# Note that we can collapse the chain after the first deref.
$same_result = $sample->{two}{bb}
# If we wanted to get an element from $my_hash, we don't have to
# dereference it and construct the new hash. We can just use the
# dereference operator.
$x = $my_hash->{a} == $thing{a}; # $x is 1 (true).
Any combination of nestings is permitted, so we could have a hash of arrays of hashes of subs, for instance.
Subs are a special case in that all we can do with them is copy their references, or call them:
$pi_times = sub { my $x = shift; return 3.14159 * $x };
$the_sub = $pi_times;
$z = $the_sub->(4); # calls the $pi_times anonymous sub
# returns pi * 4
The perldoc perlre man page goes into this in detail; perldoc perlreftut is a good tutorial which follows up what I've outlined here in a lot more detail.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With