为什么Perl允许在未经处理的数据结构上调用coderef?

Zai*_*aid 8 methods perl coderef

执行语句时$obj->method();,perldiag说Perl需要知道方法属于哪个包.这就是为什么它需要得到祝福:

无法在未完成的引用上调用方法"%s"

(F)方法调用必须知道它应该运行在哪个包中.它通常从您提供的对象引用中找到它,但在这种情况下您没有提供对象引用.在被祝福之前,引用不是对象引用.见 perlobj.

因此,不可能执行以下操作:

my $data = [
             [ 1, 2, 3 ],
             [ 4, 5, 6 ],
           ];

$data->process( @params );  # Can't call method "process" on unblessed reference
Run Code Online (Sandbox Code Playgroud)

那为什么它与coderef一起工作?:

my $process = \&process;    # Same method as before
$data->$process( @params ); # Works fine now
Run Code Online (Sandbox Code Playgroud)

mob*_*mob 22

$variable->method(@args)
Run Code Online (Sandbox Code Playgroud)

只是调用

method($variable, @args)
Run Code Online (Sandbox Code Playgroud)

但Perl在哪个包中找到method子程序?如果$variable是一个有福的引用,Perl将在返回的包中查找子例程ref $variable.如果$variable是字符串和包的名称,Perl将在该包名中查找子例程.

在您的第二个示例中,当您声明时

$process = \&process
Run Code Online (Sandbox Code Playgroud)

您已经为Perl提供了要调用的代码的引用,因此Perl知道接听电话

$variable->$process(@args)
Run Code Online (Sandbox Code Playgroud)

并调用

$process->($variable, @args)
Run Code Online (Sandbox Code Playgroud)

要么

&process($variable, @args)
Run Code Online (Sandbox Code Playgroud)

只有当$variableunblessed参考和方法名称不能被解析成一个代码参考,而Perl想不出做什么和平底船.

  • 每个脚本都有多个包(尝试`perl -E'代表grep/:: $ /,key%main ::`).但更重要的是,每个子程序调用**总是**发生在包(除了可能调用匿名子)之外,即使Perl语法经常隐藏一些细节.编译器中没有机制可以获取非限定子例程名称并在所有可用命名空间中搜索匹配的子例程名称. (2认同)

Eri*_*rom 10

当perl看到$x->$y它将它编译成类似于:

if (reftype $y eq 'CODE') {
    $y->($x)
}
else {
    if (my $code_ref = eval {$x->can($y)}) {
        $code_ref->($x)
    }
    else {
       die "error"
    }
}
Run Code Online (Sandbox Code Playgroud)

如果$y恰好是一个单词,则第一次检查始终为false,然后该else块执行常规方法调用.


Woo*_*ble 6

在第一个示例中,您尝试按名称调用数组引用的方法; 数组引用没有任何方法,所以这甚至没有意义.

在第二个例子中,你使用了类似的语法,但在这种情况下,->只是用于调用右手参数的语法糖,左手参数作为第一个参数; 它不是调用实例方法,它只是调用一个子程序,其参数以令人困惑的方式指定.