为什么 Perl 允许在不受欢迎的数据结构上调用 coderefs?

发布于 2024-12-15 18:19:22 字数 813 浏览 1 评论 0原文

执行语句$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

那么为什么它可以与 coderef 一起使用?:

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

When executing the statement $obj->method();, perldiag says that Perl needs to know what package the method belongs to. That's why it needs to be blessed:

Can't call method "%s" on unblessed reference

(F) A method call must know in what package it's supposed to run. It
ordinarily finds this out from the object reference you supply, but
you didn't supply an object reference in this case. A reference isn't
an object reference until it has been blessed. See
perlobj.

Because of this, it isn't possible to do the following:

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

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

Then why does it work with a coderef?:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

猥︴琐丶欲为 2024-12-22 18:19:22
$variable->method(@args)

只是调用

method($variable, @args)

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

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

$process = \&process

已向 Perl 提供对要调用的代码的引用时,Perl 知道要接受调用

$variable->$process(@args)

并调用

$process->($variable, @args)

or

&process($variable, @args)

仅当 $variable不受欢迎的引用,并且方法名称无法解析为代码引用,Perl 无法弄清楚要做什么和下注。

$variable->method(@args)

just invokes

method($variable, @args)

But in which package should Perl find the method subroutine? If $variable is a blessed reference, Perl will look for the subroutine in the package returned by ref $variable. If $variable is a string and the name of a package, Perl will look for the subroutine in that package name.

In your second example, when you declare

$process = \&process

you have given Perl the reference to the code you want to invoke, so Perl knows to take the call

$variable->$process(@args)

and invoke

$process->($variable, @args)

or

&process($variable, @args)

It is only when $variable is an unblessed reference, and the method name can not be resolved into a code reference, that Perl cannot figure out what to do and punts.

樱桃奶球 2024-12-22 18:19:22

当 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"
    }
}

如果 $y 恰好是一个裸字,则第一个检查始终为 false,然后else 块执行正常的方法调用。

When perl sees $x->$y it compiles it into something like:

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

If $y happens to be a bareword, the first check is always false, and then the else block performs a normal method call.

放赐 2024-12-22 18:19:22

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

在第二个示例中,您使用类似的语法,但在本例中 -> 只是用于调用右侧参数并将左侧参数作为第一个参数的语法糖;它不是调用实例方法,而是简单地调用一个子例程,其中的参数以令人困惑的方式指定。

In the first example, you're trying to call a method of an array reference by name; the array reference doesn't have any methods, so this doesn't even make sense.

In the second example, you're using similar syntax, but in this case the -> is just syntactic sugar for calling the right-hand parameter with the left-hand parameter as the first argument; it's not calling an instance method, it's simply invoking a subroutine with the parameter specified in a confusing way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文