Perl语法细节 - 列出有或没有parens的上下文?

时间:2016-01-18 18:48:44

标签: perl

这有效:

my $r = someSubroutine( map { ( 0 => $_ ) } @hosts)

这不起作用,给出语法错误:

my $r = someSubroutine( map { 0 => $_ } @hosts)

我认为我理解的是,地图之后的{ }相当于一个闭包或匿名子程序。

但是如果我在正常子例程的末尾加上“value, value”,它将返回这些值的列表。如果我对地图使用这种简洁,那就是语法错误。

3 个答案:

答案 0 :(得分:6)

首先,这是一个非常奇怪的陈述。 map生成的列表看起来像

0, $hosts[0], 0, $hosts[1], 0, $hosts[2], ...

所以它对于分配哈希是没用的,因为它与

相同
my  %hash = (0 => $hosts[-1])

map将接受 BLOCK (这是您正在使用的)或简单的 EXPRESSION 作为其第一个参数。这里的问题是{ 0 => $_ }看起来非常像一个带有单个元素的匿名哈希,它是一个 EXPRESSION ,这就是解析器猜测它的内容。在第二个参数之前, EXPRESSION 需要一个逗号,但是当perl到达map { 0 => $_ } @hosts中的右括号时,它找不到一个,因此它必须抛出语法错误,因为它太远而无法回到开口支撑并假设一个阻挡

The documentation就像这样

  

{启动散列引用和块,因此map { ...可以是映射BLOCK LIST的开头或映射EXPR,LIST。因为Perl没有预测结束},所以它必须根据它在{之后发现的内容来猜测它正在处理什么。通常情况下它是正确的,但如果它没有,它将不会意识到出现问题,直到它到达}并遇到丢失(或意外)的逗号。语法错误将在}附近报告,但您需要更改{附近的内容,例如使用一元+或分号为Perl提供一些帮助

解决方案是在您发现时消除歧义。其中任何一个都可以使用

map +( 0 => $_ ), @hosts

map(( 0 => $_ ), @hosts)

map { +0 => $_ } @hosts

map { ( 0 => $_ ) } @hosts

map { ; 0 => $_ } @hosts

答案 1 :(得分:4)

map有两种语法:

map BLOCK LIST   e.g. map { f() } g()
map EXPR, LIST   e.g. map f(), g()

当Perl遇到map时,需要确定使用了哪种语法。假设map之后的第一个令牌是{。这是BLOCK的开始,对吧?坚持,稍等!表达式也可以从{开始!

my $hash_ref = { key => 'val' };

语法含糊不清。 Perl必须“猜测”您正在使用哪种语法。 Perl展望下一个令牌以帮助猜测,但有时它仍然猜错了。这是其中一种情况。

以下是此标准的解决方法:

map {; ... } LIST    # Force Perl to recognize the curly as the start of a BLOCK
map +{ ... }, LIST   # Force Perl to recognize the curly as the start of a hash constructor
  • ;不能成为哈希构造函数的一部分,因此{只能启动BLOCK。
  • +必须启动EXPR(而不是BLOCK)。这是一个在这种情况下无助于帮助的运营商。

例如,

map {; +{ $row->{id} => $row->{val} } } @rows

答案 2 :(得分:1)

maphttp://perldoc.perl.org/functions/map.html

中的perldoc对此进行了描述

简而言之,你应该使用像parens或+这样的小助手 - 符号,这样perl就能正确解析{...}构造:

my $r = someSubroutine( map { + 0 => $_ } @hosts)