我想知道为什么以下语法失败
#!/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";
答案 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的程序员会很快谴责它的模糊不清。