#!/usr/bin/perl
sub f { {
a => 1,
b => 2
} }
sub g { {
%{f()},
c => 3,
d => 4,
} }
use Data::Dumper;
print Dumper g();
The above code outputs
$VAR1 = 'a';
$VAR2 = 1;
$VAR3 = 'b';
$VAR4 = 2;
$VAR5 = 'c';
$VAR6 = 3;
$VAR7 = 'd';
$VAR8 = 4;
despite in my understanding it should output
$VAR1 = {
'a' => 1,
'c' => 3,
'b' => 2,
'd' => 4
};
What is my misunderstanding?
The Perl language has ambiguities. Take for example
{ }
is valid syntax for a block ("bare loop").{ }
is valid syntax for a hash constructor.And both are allowed as a statement!
So Perl has to guess. Perl usually guesses correctly, but not always. In your case, it guessed correctly for
f()
, but not forg()
.To fix this, you can give Perl "hints". Unary-
+
can be used to do this. Unary-+
is a completely transparent operator; it does nothing at all. However, it must be followed by an expression (not a statement).{ }
has only one possible meaning as an expression.Similarly, you can trick Perl to guess the other way.
So in this case, you could use
or
(
return
must also be followed by an expression if anything.)The problem is that a pair of braces is ambiguous in Perl, and may be either a block or an anonymous hash
Because of the contents of the hash in your
g
(please use better names) perl has assumed that you are writing a code block, which is just a list of scalar valuesMake it more explicit like this and your code will function as you expect
output