取消引用子例程语法

时间:2014-03-19 23:06:23

标签: perl reference anonymous-methods

我想知道为什么以下语法失败

 #!/usr/bin/env perl

use warnings;
use strict;

sub add { return $_[0]+5; };
my $add_ref = \&add;

my $result = 0;

$result = &add(5);
print " result is $result \n";

$result = add(5);
print " result is $result \n";

#$result = $add_ref(5);  ---------------> fail
#print " result is $result \n";

#$result = {$add_ref}(5); -----------------> fail
#print " result is $result \n";

$result =  &{$add_ref}(5);
print " result is $result \n";

$result =  $add_ref->(5);
print " result is $result \n";

1)我刚刚用add替换了函数{$add_ref}的名称,这是中级Perl书中提到的方法。在函数调用中&是可选的,但在这种情况下为什么不呢。

2)我还发现$reference_to_anonymous_subroutine(parameter)有效,但$reference_to_names_subroutine(parameter)

实施例

my @array = (1, sub { my $n = $_[0]; $n = $n +5;});

my $result = $array[1](2); ---------> works and does not need &{$array[1]}(2)
print "$result \n"; 

2 个答案:

答案 0 :(得分:3)

  

在函数调用&中是可选的,但在这种情况下为什么不呢。

在子程序中,调用&是可选的,但只有在您已经拥有子程序时才需要,而不是在需要首先解除引用时。

取消引用某些内容的首选方法是->符号。

$subroutine_ref->(5); 
$hash_ref->{'key'};
$array_ref->[5];

当然TIMTOWTDI,您可以使用键入的符号而不是->取消引用:

 &$subroutine_ref(5);  # same effect as $subroutine_ref->(5)

但我发现它的可读性较差。


my $result = $array[1](2); # works and does not need &{$array[1]}(2)

如果深度达到多个级别,则部分之间的->是隐含的且可选的。

$array[1](2); # shorthand for $array[1]->(2);

你可能仍然需要第一个:如果你有一个数组引用而不是一个数组,你会做

$array_ref->[1](2);

答案 1 :(得分:1)

问题是Perl必须对你的意思做出可靠的猜测。

鉴于$add_ref

的定义
sub add { return $_[0]+5; };
my $add_ref = \&add;
"适当的"调用子例程的方法是使用间接运算符->,它实际上取消引用它的左操作数(类似于"胖逗号" =>隐式引用其左操作数)

所以你可以明确地将dereference写为

&$add_ref(5)

或使用

隐式执行
$add_ref->(5)

Perl总是非常努力地通过你所写的内容弄清楚你的意思,所以我相信你的意见已经解决了

$result = $add_ref(5)  # Syntax error

作为间接子程序调用会导致模糊性问题。

你的第二个陈述更清楚

$result = {$add_ref}(5)  # Syntax error

这是一个语法错误,因为裸块无法返回值。 (事实上​​,您使用单个键声明匿名哈希,没有值,然后尝试调用它。)如果您使用do和间接运算符,那么一切都很好。喜欢这个

$result = do{$add_ref}->(5)

但我不推荐它。或者您可以将块放在上下文中,就像您在下一个示例中所做的那样,然后编写

$result = &{$add_ref}(5)

,因为首先发生取消引用,与

相同
$result = &$add_ref(5)

虽然Perl引用可能看起来令人困惑,但随着您习惯该语言,它将变得更加清晰。由于作者Larry Wall在语言学方面的背景,它非常像一种非常正式的自然语言。在每种口语中都有无穷无尽的"不规则的"单词,他们已经开发出这种方式,因为使用它们的人发现它最方便。没有其他"为什么",但这是为什么花费少于几个月与Perl的程序员会很快谴责它的模糊不清。