Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

perl - usage of $ symbol

Tags:

syntax

hash

perl

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.

like image 468
Mohan Avatar asked Nov 18 '25 14:11

Mohan


2 Answers

No, the sigils refer to the mode of access. $ means a single element, @ means multiple elements and % means key/value pairs. Demo:

no references involved

$myhash1{a}             # 1
@myhash1{qw(a b)}       # (1, 2)
%myhash1{a}             # (a => 1)

with references involved

$$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.
  • Any of %$myhash2, %{ $myhash2 }, $myhash2->%* means: all k/v pairs in the dereferenced hash.
like image 104
daxim Avatar answered Nov 21 '25 05:11

daxim


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:

  • Use the backslash (\) 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.
  • Use one of the anonymous constructors to build a reference to a hash or array.
  • Construct a subroutine (function) reference in-line with an anonymous subroutine.

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.

  1. Use stacked sigils. These read from right to left; each sigil dereferences the variable again. This is most often used to dereference a scalar. You'll usually only see two, but sometimes multiple levels of dereferencing are done at once to go through a chain of scalar values. Stacked sigils can be confusing, mostly because they add a right-to-left interpretation to a language that is read primarily left-to-right.
  2. Use a sigil and paired braces. This is the logical equivalent of using parens to disambiguate expressions. What's inside the braces is dereferenced as the type outside the braces. Most often used to get aggregate types from a reference.
  3. Use a chained series of dereference operators. Each dereference implies that the lefthand side is a scalar reference, so several in a row implies that the result of each dereference is another (scalar) reference. Handy for digging down into a structure to find something.

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.

like image 25
Joe McMahon Avatar answered Nov 21 '25 05:11

Joe McMahon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!