为什么这段 Perl 代码没有错误

4

I'm writing a WxPerl program and instead of

$panel->SetDropTarget( MyTextDropTarget->new($panel) );

我写了

$panel->SetDropTarget->( MyTextDropTarget->new($panel) );

Perl没有抱怨。(Perl调用了某个带有一些参数的函数,脚本出现了错误并显示了以下错误信息:

Usage: Wx::Window::SetDropTarget(THIS, target) at ./x.pl line 230.

我很好奇Perl是如何解析'错误'版本的。

添加编辑:

好的,如果$x = \&some_function,那么我理解为什么会这样。

$x->($arg1, $arg2, ...)

调用了一些函数some_function($arg1, $arg2, ...)。

runrig的例子是其中一种可能性,但我非常确定: 1)$panel包含一个经过blessed处理的对象引用,而不是一个字符串。 2)SetDropTarget是$panel的一个基类方法。

从错误信息中我们可以推断出正在调用SetDropTarget()。如果runrig的例子仍然适用于这里(我猜它确实适用),那么即使SetDropTarget后面没有括号,也就是说我有

$panel->SetDropTarget->

替换为

 $panel->SetDropTarget()->

Perl仍在调用SetDropTarget吗?(它检查其参数的数量和类型,然后在运行时致命地抱怨)。这是发生的事情吗?
3个回答

6
您的 SetDropTarget 可能没有返回代码引用,但在运行时无法确定:
#!/usr/bin/perl

my $panel = 'main';

$panel->SetDropTarget->("bloomin'");

sub SetDropTarget {
  return sub { print "Set the $_[0] drop target!\n" }
}

6

因为这是完全有效的语法。 $panel->SetDropTarget->( MyTextDropTarget->new($panel) ) 的意思是“从$panel调用&SetDropTarget方法,然后解除子引用返回的&SetDropTarget。”我猜你并不是想写这个,但任何错误都会在运行时抛出,即使是在严格模式下。


4
补充一下Richard Simões所说的:当一个方法不需要参数时,括号是可选的;也就是说,$foo->bar()可以写成$foo->bar。这就是为什么$panel->SetDropTarget->(...)被理解为$panel->SetDropTarget()->(...)的原因。 - ruakh

1

Perl解析

$panel->SetDropTarget->( MyTextDropTarget->new($panel) );

意思是"$panel是一个对象;调用它的SetDropTarget方法(可选省略括号),该方法将返回一个sub的引用;调用该sub,并将MyTextDropTarget->new($panel)的结果作为其唯一参数传递。"

也就是说,Perl期望SetDropTarget在以下代码中类似于foo

sub foo {
    return sub {
        my $bar = shift;
        return $bar . ', world!'; 
    }
}

foo()->('Hello');
foo->('Goodby');

我相当确定这是错误的 - 有两个函数调用发生,而不仅仅是你所指示的一个。(请参见@runrig的示例) - jwd
2
我不会说“一个成员”,而是“一个方法”。也不是“它本身是对子例程的引用”,而是“它返回对子例程的引用”。 - runrig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接