Cary Millsap Cary Millsap - 7 months ago 9
Perl Question

Why is (a=>1,b=>2){a} a syntax error?

I want to use a hash in an expression. No problem:

use strict;
use warnings;
my %h = (a=>1, b=>2);
my $h = $h{a};
print "h='$h'\n";


But since I will refer to it only once, I don't want to name it. Naively substituting the hash content for $h doesn't work. The following code produces a syntax error on line 3 at "){":

use strict;
use warnings;
my $x = (a=>1, b=>2){a};
print "x='$x'\n";


I know that the following is the way to accomplish what I need:

use struct;
use warnings;
my $y = {a=>1, b=>2}->{a};
print "y='$y'\n";


Why doesn't the second example work?

EDIT 1: This is a MVCE. In real life, my hash key ('a' in this example) is not a constant.

EDIT 2: A little more about my motive: I don't want an unnecessary variable in scope in my code, so if I were to restrict the scope of %h to where it really belongs, I would have this:

use strict;
use warnings;
my $h;
{
my %h = (a=>1, b=>2);
$h = $h{a};
}
print "h='$h'\n";


I don't want to leave %h in scope for more code than I need, but it's also clunky to write the code segment with the extra block for scoping. This is why I was looking for a clean one-line way to make the assignment.

Answer

See, (something1, something2, ...) is not an array constructor. It's just a way to say to interpreter that "we have something in a list context". You can understand each (a,b,c,...) usage like an assignment to an array with no name. So, yes we can get a value from this array by index. ('a' => 1, 'b' => 2)[1] will return 1.

Hash will be created only after assignment in list context if left side is a hash variable. Before assignment we can't use this list like hash because we don't have hash. So postcircumfix operation {...} is not allowed.