1

Just starting with Perl, and I used the wrong pair of parentheses for this code example:

@arr = {"a", "b", "c"};
print "$_\n" foreach @arr;

I mean, I can of course see WHAT it does when I run it, but I don't understand WHY it does that. Shouldn't that simply fail with a syntax error?

6
  • 5
    Welcome to perl. Always include use strict; and use warnings; at the top of EVERY perl script. In this instance, you would've gotten the warning Odd number of elements in anonymous hash which could've also clued you in to the mistype. Commented Aug 6, 2014 at 13:58
  • 3
    @Miller: Unless the OP added a fourth element, in which case perl would proceed silently. Commented Aug 6, 2014 at 14:12
  • 1
    @Miller: And always spell it Perl ;) Commented Aug 6, 2014 at 14:28
  • @Borodin: Unless you're talking about the interpreter (as I was). :) stackoverflow.com/questions/72312/how-should-i-capitalize-perl Commented Aug 6, 2014 at 14:46
  • @Borodin, "perl" is proper if you are referring to the program/executable. Commented Aug 6, 2014 at 14:48

3 Answers 3

3

You have accidentally created an anonymous hash, which is a hash that has no identifier and is accessed only by reference.

The array @arr is set to a single element which is a reference to that hash. Properly written it would look like this

use strict;
use warnings;

my @arr = (
  {
    a => "b",
    c => undef,
  }
);

print "$_\n" foreach @arr;

which is why you got the output

HASH(0x3fd36c)

(or something similar) because that is how Perl will represent a hash reference as a string.

If you want to experiment, then you can print the value of the first hash element by using $arr[0] as a hash reference (the array has only a single element at index zero) and accessing the value of the element with key a with print $arr[0]->{a}, "\n".

Note that, because hashes have to have a multiple of two values (a set of key/value pairs) the hash in your own code is implicitly expanded to four values by adding an undef to the end.

It is vital that you add use strict and use warnings to the top of every Perl program you write. In this case the latter would have raised the warning

Odd number of elements in anonymous hash
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. Your answer also explains why @arr is still an array, even though it was initialized as a hash.
It wasn't initialized as a hash. 1) As I explained, {} returns a scalar, and you can definitely assign a list of scalars to an array. (e.g. my @a = ('a');) 2) That would be wrong to assign to hash.
3

It can be surprising how few things are syntax errors in Perl. In this case, you've stumbled onto the syntax for creating an an anonymous hash reference: { LIST }. Perl doesn't require the use of parentheses (the () kind) when initializing an array1. Arrays hold ordered lists of scalar (single) values and references are scalars so perl happily initializes your array with that reference as the only element.

It's not what you wanted, but it's perfectly valid Perl.

The () override the precedence of the operators and thus changes the behavior of the expression. @a = (1, 2, 3) does what you'd expect, but @a = 1, 2, 3 means (@a = 1), 2, 3, so it only assigns 1 to @a.

1 Comment

@ikegami: I was struggling to find the wording for a subtle point and failed. :( I've restored your edits.
2

{ LIST } is the hash constructor. It creates a hash, assigns the result of LIST to it, and returns a reference to it.

my $h = {"a", "b", "c", "d"};
say $h->{a};  # b

A list of one hash ref is just as legit as any other list, so no, it shouldn't be a syntax error.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.