#!/usr/bin/perl
sub f { {
a => 1,
b => 2
} }
sub g { {
%{f()},
c => 3,
d => 4,
} }
use Data::Dumper;
print Dumper g();
上面的代码输出
$VAR1 = 'a';
$VAR2 = 1;
$VAR3 = 'b';
$VAR4 = 2;
$VAR5 = 'c';
$VAR6 = 3;
$VAR7 = 'd';
$VAR8 = 4;
尽管我认为它应该输出
$VAR1 = {
'a' => 1,
'c' => 3,
'b' => 2,
'd' => 4
};
我的误会是什么?
答案 0 :(得分:9)
问题在于,Perl中的一对大括号不明确,可能是一个块或一个匿名哈希
由于您g
中的哈希内容(请使用更好的名称),perl假设您正在编写一个代码块,它只是一个标量值列表
像这样使它更加明确,您的代码将按预期运行
use strict;
use warnings 'all';
sub foo {
{
a => 1,
b => 2,
}
}
sub bar {
my $href = {
%{ foo() },
c => 3,
d => 4,
}
}
use Data::Dump;
dd bar();
{ a => 1, b => 2, c => 3, d => 4 }
答案 1 :(得分:7)
Perl语言有歧义。举个例子
sub some_sub {
{ } # Is this a hash constructor or a block?
}
{ }
是一个块(“裸循环”)的有效语法。
{ }
是哈希构造函数的有效语法。
两者都可以声明!
因此Perl必须猜测。 Perl通常猜测正确,但并非总是如此。对于您来说,它对于f()
正确猜出了,但对g()
却猜不出来。
要解决此问题,可以为Perl提供“提示”。一元-+
可用于执行此操作。一元-+
是一个完全透明的运算符;它什么都不做。但是,必须在其后跟随一个表达式(而不是语句)。 { }
仅具有一种可能的含义。
+{ } # Must be a hash constructor.
类似地,您可以欺骗Perl进行另一种猜测。
{; } # Perl looks ahead, and sees that this must be a block.
因此,在这种情况下,您可以使用
sub g { +{
%{f()},
c => 3,
d => 4,
} }
或
sub g { return {
%{f()},
c => 3,
d => 4,
} }
({return
之后还必须带有表达式。)