这是我不明白的事情。
此脚本正常工作(注意地图功能中的连接):
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my %aa = map { 'a' . '' => 1 } (1..3);
print Dumper \%aa;
__END__
output:
$VAR1 = {
'a' => 1
};
但是没有连接,地图就不起作用了。这是我希望工作的脚本,但它没有:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my %aa = map { 'a' => 1 } (1..3);
print Dumper \%aa;
__END__
output:
Not enough arguments for map at e.pl line 7, near "} ("
syntax error at e.pl line 7, near "} ("
Global symbol "%aa" requires explicit package name at e.pl line 9.
Execution of e.pl aborted due to compilation errors.
你能解释一下这种行为吗?
答案 0 :(得分:12)
Perl使用启发式方法来决定您是否正在使用:
map { STATEMENTS } LIST; # or
map EXPR, LIST;
因为虽然" {"通常是块的开始,它也可能是hashref的开始。
这些启发式方法在令牌流(IIRC两个令牌)中远远不能向前看。
你可以强迫" {"使用:
解释为块map {; STATEMENTS } LIST; # the semicolon acts as a disambigator
你可以强迫" {"使用:
解释为哈希map +{ LIST }, LIST; # the plus sign acts as a disambigator
grep
同样受到影响。 (技术上do
也是如此,因为hashref可以作为参数给出,然后将其进行字符串化并将其视为文件名。但这只是奇怪的。)
答案 1 :(得分:6)
根据map
的{{3}}:
因为Perl没有提前结束
}
,所以它必须根据{
之后的内容来猜测它正在处理什么。通常它是正确的,但如果它没有意识到某些事情是错误的,直到它到达}
举例:
%hash = map { "\L$_" => 1 } @array # perl guesses EXPR. wrong
%hash = map { +"\L$_" => 1 } @array # perl guesses BLOCK. right
所以添加+
会给你与你给出的第一个例子相同
my %aa = map { +'a'=> 1 } (1..3);
答案 2 :(得分:3)
Perl的manpage entry for map()解释了这一点:
"{" starts both hash references and blocks, so "map { ..." could be either the start of map BLOCK LIST or map EXPR, LIST. Because Perl doesn't look ahead for the closing "}" it has to take a guess at which it's dealing with based on what it finds just after the "{". Usually it gets it right, but if it doesn't it won't realize something is wrong until it gets to the "}" and encounters the missing (or unexpected) comma. The syntax error will be reported close to the "}", but you'll need to change something near the "{" such as using a unary "+" to give Perl some help: %hash = map { "\L$_" => 1 } @array # perl guesses EXPR. wrong %hash = map { +"\L$_" => 1 } @array # perl guesses BLOCK. right %hash = map { ("\L$_" => 1) } @array # this also works %hash = map { lc($_) => 1 } @array # as does this. %hash = map +( lc($_) => 1 ), @array # this is EXPR and works! %hash = map ( lc($_), 1 ), @array # evaluates to (1, @array) or to force an anon hash constructor use "+{": @hashes = map +{ lc($_) => 1 }, @array # EXPR, so needs comma at end to get a list of anonymous hashes each with only one entry apiece.
基于此,要摆脱连接kludge,您需要将语法调整为其中之一:
my %aa = map { +'a' => 1 } (1..3);
my %aa = map { ('a' => 1) } (1..3);
my %aa = map +( 'a' => 1 ), (1..3);
答案 3 :(得分:2)
在地图的背景下,大括号有点模棱两可。它们可以像你想要的那样围绕一个块,或者它们可以是一个匿名的哈希构造函数。 perl解析器中有一些模糊逻辑,它试图猜测你的意思。
你的第二个案例看起来更像是perl的匿名哈希。
请参阅解释此问题的perldoc for map并提供一些解决方法。