这有效:
my $r = someSubroutine( map { ( 0 => $_ ) } @hosts)
这不起作用,给出语法错误:
my $r = someSubroutine( map { 0 => $_ } @hosts)
我想我理解的是,映射后的{ }
相当于闭包或匿名子例程。
但是如果我在正常子例程的末尾放一个"value, value
",它将返回这些值的列表。如果我在地图中使用这种简洁性,那就是语法错误。
首先,这是一个非常奇怪的说法。map
生成的列表如下所示
0, $hosts[0], 0, $hosts[1], 0, $hosts[2], ...
所以分配给哈希是没有用的,因为它与
my %hash = (0 => $hosts[-1])
map
将接受 BLOCK(这是您正在使用的)或其第一个参数的简单表达式。这里的问题是{ 0 => $_ }
看起来非常像一个带有单个元素的匿名哈希,这是一个表达式,这就是解析器猜测的。表达式要求在它后面,在第二个参数之前有一个逗号,但是当perl到达map { 0 => $_ } @hosts
中的右大括号时,它找不到一个逗号,所以它必须抛出一个语法错误,因为它太远了,无法回溯到左大括号并假设一个块
文档是这样说
的
{
同时启动哈希引用和块,因此map { ...
可以是映射块列表或映射 EXPR,列表的开头。因为 Perl 不会展望收盘}
所以它必须根据它在{
后发现的内容来猜测它正在处理什么。通常它做对了,但如果它没有,它不会意识到有什么问题,直到它到达}
并遇到丢失(或意外)的逗号。语法错误将在}
附近报告,但您需要更改{
附近的一些内容,例如使用一元+
或分号为 Perl 提供一些帮助
解决方案是在您发现时消除歧义。这些中的任何一个都可以工作
map +( 0 => $_ ), @hosts
map(( 0 => $_ ), @hosts)
map { +0 => $_ } @hosts
map { ( 0 => $_ ) } @hosts
map { ; 0 => $_ } @hosts
map
有两种语法:
map BLOCK LIST e.g. map { f() } g()
map EXPR, LIST e.g. map f(), g()
当Perl遇到map
时,它需要确定使用了哪种语法。假设 map
之后的第一个令牌是 {
。这就是区块的开始,对吧?坚持!表达式也可以以{
开头!
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(而不是一个块)。在这种情况下,这是一个除了提供帮助之外什么都不做的操作员。
例如
map {; +{ $row->{id} => $row->{val} } } @rows
在 perldoc on map
中有描述: http://perldoc.perl.org/functions/map.html
简而言之,你应该使用像 parens 或 +
-symbol 这样的小助手,这样 perl 就能够正确解析{...}
构造:
my $r = someSubroutine( map { + 0 => $_ } @hosts)