Why do you need $ when accessing array and hash elements in Perl?
Asked Answered
F

9

12

Since arrays and hashes can only contain scalars in Perl, why do you have to use the $ to tell the interpreter that the value is a scalar when accessing array or hash elements? In other words, assuming you have an array @myarray and a hash %myhash, why do you need to do:

$x = $myarray[1];
$y = $myhash{'foo'};

instead of just doing :

$x = myarray[1];
$y = myhash{'foo'};

Why are the above ambiguous?

Wouldn't it be illegal Perl code if it was anything but a $ in that place? For example, aren't all of the following illegal in Perl?

@var[0];
@var{'key'};
%var[0];
%var{'key'};
Floriated answered 30/9, 2008 at 15:44 Comment(1)
all the myhash lines should be of the form myhash{'foo'} - curly braces for hashes, not square ones.Sophey
S
17

Slices aren't illegal:

@slice = @myarray[1, 2, 5];
@slice = @myhash{qw/foo bar baz/};

And I suspect that's part of the reason why you need to specify if you want to get a single value out of the hash/array or not.

Sophey answered 30/9, 2008 at 15:55 Comment(0)
T
22

I've just used

my $x = myarray[1];

in a program and, to my surprise, here's what happened when I ran it:

$ perl foo.pl 
Flying Butt Monkeys!

That's because the whole program looks like this:

$ cat foo.pl 
#!/usr/bin/env perl

use strict;
use warnings;

sub myarray {
  print "Flying Butt Monkeys!\n";
}

my $x = myarray[1];

So myarray calls a subroutine passing it a reference to an anonymous array containing a single element, 1.

That's another reason you need the sigil on an array access.

Traduce answered 30/9, 2008 at 16:43 Comment(0)
S
17

Slices aren't illegal:

@slice = @myarray[1, 2, 5];
@slice = @myhash{qw/foo bar baz/};

And I suspect that's part of the reason why you need to specify if you want to get a single value out of the hash/array or not.

Sophey answered 30/9, 2008 at 15:55 Comment(0)
M
11

The sigil give you the return type of the container. So if something starts with @, you know that it returns a list. If it starts with $, it returns a scalar.

Now if there is only an identifier after the sigil (like $foo or @foo, then it's a simple variable access. If it's followed by a [, it is an access on an array, if it's followed by a {, it's an access on a hash.

# variables
$foo
@foo

# accesses
$stuff{blubb} # accesses %stuff, returns a scalar
@stuff{@list} # accesses %stuff, returns an array
$stuff[blubb] # accesses @stuff, returns a scalar
              # (and calls the blubb() function)
@stuff[blubb] # accesses @stuff, returns an array

Some human languages have very similar concepts.

However many programmers found that confusing, so Perl 6 uses an invariant sigil.

In general the Perl 5 compiler wants to know at compile time if something is in list or in scalar context, so without the leading sigil some terms would become ambiguous.

Merrilee answered 30/9, 2008 at 15:44 Comment(2)
Larry Wall touched on this in this interview (video).... news.oreilly.com/2008/07/larry-wall-at-oscon-open-sourc.htmlPartee
Something that starts with an @ returns a list, not an array. Using the [] indexers doesn't necessarily work on an array, either. It could be a list.Blare
G
9

This is valid Perl: @var[0]. It is an array slice of length one. @var[0,1] would be an array slice of length two.

@var['key'] is not valid Perl because arrays can only be indexed by numbers, and the other two (%var[0] and %var['key']) are not valid Perl because hash slices use the {} to index the hash.

@var{'key'} and @var{0} are both valid hash slices, though. Obviously it isn't normal to take slices of length one, but it is certainly valid.

See the slice section of perldata perldocfor more information about slicing in Perl.

Gangster answered 30/9, 2008 at 15:59 Comment(0)
B
9

People have already pointed out that you can have slices and contexts, but sigils are there to separate the things that are variables from everything else. You don't have to know all of the keywords or subroutine names to choose a sensible variable name. It's one of the big things I miss about Perl in other languages.

Blare answered 30/9, 2008 at 17:24 Comment(2)
I see. So if you are programming on a monochrome terminal, and don't have an IDE with syntax highlighting, and are using several modules from CPAN, it increases code readability.Digenesis
No, IDEs and syntax highlighting have nothing to do with it. It's the reasons I listed in my answer.Blare
Y
7

I can think of one way that

$x = myarray[1];

is ambiguous - what if you wanted a array called m?

$x = m[1];

How can you tell that apart from a regex match?

In other words, the syntax is there to help the Perl interpreter, well, interpret!

Ylem answered 30/9, 2008 at 15:50 Comment(2)
That's a typo in the original question. Since $y = myhash{foo} and $y = myarray[1] are already indicated to the interpreter by the curly and square braces.Sophey
Argument still applies, but I'll correct it to refer to myarrayYlem
H
6

In Perl 5 (to be changed in Perl 6) a sigil indicates the context of your expression.

  • You want a particular scalar out of a hash so it's $hash{key}.
  • You want the value of a particular slot out of an array, so it's $array[0].

However, as pointed out by zigdon, slices are legal. They interpret the those expressions in a list context.

  • You want a lists of 1 value in a hash @hash{key} works
  • But also larger lists work as well, like @hash{qw<key1 key2 ... key_n>}.

  • You want a couple of slots out of an array @array[0,3,5..7,$n..$n+5] works

  • @array[0] is a list of size 1.

There is no "hash context", so neither %hash{@keys} nor %hash{key} has meaning.

So you have "@" + "array[0]" <=> < sigil = context > + < indexing expression > as the complete expression.

Hogback answered 30/9, 2008 at 15:44 Comment(1)
Plus it is a hold back from Perl4.Satiated
D
4

The sigil provides the context for the access:

  • $ means scalar context (a scalar variable or a single element of a hash or an array)
  • @ means list context (a whole array or a slice of a hash or an array)
  • % is an entire hash
Dragline answered 30/9, 2008 at 16:21 Comment(3)
It is all about Context. Understanding that you can better see Perl.Forereach
The sigils do not decide context. consider $x = @array or $n = keys %hash.Blare
- & is a subroutine sigil - * is for a typeglob sigilBorderland
M
4

In Perl 5 you need the sigils ($ and @) because the default interpretation of bareword identifier is that of a subroutine call (thus eliminating the need to use & in most cases ).

Mcintosh answered 30/9, 2008 at 18:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.