【问题标题】:Perl: prototype in anonymous subroutinePerl:匿名子程序中的原型
【发布时间】:2023-03-26 14:01:01
【问题描述】:

我目前正在学习关于类型团和命名空间的 Perls 系统。所以我写了一个模块,它接受两个参数,一个常量的值和名称,并将常量导出给调用者。 $package 变量等于 caller[2]。

*{"$package::$name"} = sub () { return $value; };

上面的代码完成了将匿名子例程导出到调用者符号表的工作。因为我的目标是构建自己的常量实现,所以子程序有一个空原型,这意味着它是一个只读子程序。

但这是我的问题:原型不起作用。所以

print &TestConst; #works well
print TestConst(); #works well
print TestConst; #Name "main::TestConst" used only once: possible typo at testscript.pl line 7.

我的想法有问题吗?还有其他方法吗?

【问题讨论】:

    标签: namespaces prototype perl typeglob


    【解决方案1】:

    你可以在运行时定义你想要的所有符号,但是原型只会影响之后编译的代码,因为原型会影响对 sub 的调用如何被解析和编译。例如:

    use strict;
    use warnings;
    
    package Foo;
    
    BEGIN {
        *Foo::bar = sub () { 42 };
    }
    
    *Foo::baz = sub () { 43 };
    
    my $bar = bar;
    my $baz = baz;
    
    print "bar = [$bar], baz = [$baz]\n";
    

    如果我们运行它,它会死:

    在 tprot.pl 行使用“strict subs”时不允许使用裸词“baz” 13.

    这是由strict 引起的编译时间错误:编译器看到符号baz 并且不知道它是什么,因为typeglob *Foo::baz 不会被更改,直到运行。但是bar 工作正常,因为它是在BEGIN 块中定义的,在编译期间会立即执行。

    IOW,因为裸词是模棱两可的,Perl 需要在编译时知道它是 sub 还是其他东西。因此,您可以在 import(在隐式 BEGIN 块中执行)期间安装这些,但不能在运行时安装。

    此外,原型会影响编译语义;一个常量子程序(如constant.pm 制作的子程序)会被优化掉。其他原型会导致解析器改变其行为(例如,可以采用代码块的子程序。)编译器必须在代码中实际遇到对子程序的调用之前了解所有这些内容,以便正确解析它们。代码在所有内容都已解析后运行。

    使用显式括号或 & 号调用 sub 没有此限制,因为 Perl 在运行时足够聪明,可以知道这些是子例程调用,并在符号表中动态查找它们。

    【讨论】:

    • 即使我知道原型是在编译时处理的,但在我以前的脚本和模块中并没有真正影响到我。有时,您只需要有人将您的思想推向正确的方向。非常感谢。
    • 另一个选项是使用符号延迟编译代码。例如my $baz = eval "baz";.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 2011-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多