gpt4 book ai didi

perl - 让 perl 向前看子原型(prototype)

转载 作者:行者123 更新时间:2023-12-01 12:09:02 29 4
gpt4 key购买 nike

Perl 有点过于宽容:如果您将额外的参数传递给 sub,它们将被忽略。

为了避免这种情况,我想使用原型(prototype)来确保为每个 sub 提供正确数量的参数。

只要我在使用它之前声明原型(prototype)就可以正常工作:

sub mysub($);
sub mysub2($);

mysub(8);
mysub(8,2); # Complain here

sub mysub($) {
mysub2($@);
}

sub mysub2($) {
if($_[0] == 1) {
mysub(2);
}
print $@;
}

但我真的很讨厌把它分开。我更希望 Perl 阅读完整的文件以查看是否还有进一步的声明。所以我想写这样的东西:

use prototypes_further_down; # This does not work

mysub(8);
mysub(8,2); # Complain here

sub mysub($) {
mysub2($@);
}

sub mysub2($) {
if($_[0] == 1) {
mysub(2);
}
print $@;
}

我能以某种方式要求 Perl 这样做吗?

最佳答案

To avoid this I would like to use prototypes to make sure each sub is given the correct amount of arguments.

不,你不会。尽管名称相似,Perl 原型(prototype)不是你父亲的函数原型(prototype)。引用 The Problem with Prototypes (强调我的),

Perl 5's prototypes serve two purposes. First, they're hints to the parser to change the way it parses subroutines and their arguments. Second, they change the way Perl 5 handles arguments to those subroutines when it executes them. A common novice mistake is to assume that they serve the same language purpose as subroutine signatures in other languages. This is not true.

除了它们没有相同的预期目的之外,绕过原型(prototype)是微不足道的,因此它们没有提供实际保护来防止有人故意以(您认为的)“错误”方式调用您的代码。作为perldoc perlsub告诉我们,

The function declaration must be visible at compile time. The prototype affects only interpretation of new-style calls to the function, where new-style is defined as not using the & character. In other words, if you call it like a built-in function, then it behaves like a built-in function. If you call it like an old-fashioned subroutine, then it behaves like an old-fashioned subroutine. It naturally falls out from this rule that prototypes have no influence on subroutine references like \&foo or on indirect subroutine calls like &{$subref} or $subref->().

Method calls are not influenced by prototypes either, because the function to be called is indeterminate at compile time, since the exact code called depends on inheritance.

即使您可以让它提示 mysub(8,2)&mysub(8,2)$subref =\&mysub; $subref->(8,2) 或(如果 mysubpackage MyModule 中的对象方法)$o = MyModule->new; $o->mysub(8,2) 将毫无怨言地工作。

如果您想使用核心 Perl(5.20 之前的版本)验证您的子程序是如何被调用的,那么您需要自己在子程序的主体中执行验证。 Perl 5.20 和更新版本有一个(在撰写本文时为“实验性”)Signatures sub declarations 的扩展可能对你有用,但我自己从未使用过,所以我不能说它的有效性或局限性。还有很多CPAN可用于处理此类事情的模块,您可以通过搜索“签名”或“原型(prototype)”等内容来找到它们。

无论您选择哪种方法,除非您在使用这些签名之前定义这些签名,否则您将无法获得有关不正确函数签名的编译时错误。在您的示例中,两个 sub 相互调用的情况下,这可以通过使用前向声明预先建立其签名来实现:

sub mysub($foo);                               # Forward declaration
sub mysub2 { mysub(8) }
sub mysub { mysub2('infinite loops ftw!') } # Complete version of the code

关于perl - 让 perl 向前看子原型(prototype),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53975033/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com