16

我有一个这样的 Perl 文件:

use strict;
f1();

sub f3()
{ f2(); }

sub f1()
{}
sub f2()
{}

简而言之,f1在定义之前被调用。因此,Perl 抛出一个警告:“f1 调用太早,无法检查原型”。但情况也是如此f2,唯一的区别是它是从另一个子例程内部调用的。它不会为f2. 为什么?

解决此问题的最佳方法是什么?

  1. 在调用子程序之前声明它
  2. 像这样调用子:&f1();
4

6 回答 6

18

You can completely avoid this issue by not using prototypes in the first place:

use strict;

f1();

sub f3 { f2() }

sub f1 {}
sub f2 {}

Don't use prototypes unless you know why you are using them:

This is all very powerful, of course, and should be used only in moderation to make the world a better place.

于 2009-11-12T05:16:51.033 回答
16

只需从您的子例程定义中删除 ()。当你用 () 定义时,Perl 认为这些是原型,你必须在使用它之前定义你的原型。

尝试这个:

use strict;
f1();

sub f3
{ f2(); }

sub f1
{}
sub f2
{}
于 2015-06-06T00:26:53.343 回答
4

在 Perl 中定义函数时,不应使用括号。当你这样做时,你会得到这个错误。这是错误的:

sub DoSomthing(){
   #do what ever...
}

这是要走的路:

sub DoSomthing{
   #do what ever...
}

没有括号。

有关更详细的说明,请参阅 Gabor Szabo 的 Perl Maven 页面,了解 Perl 中的子例程和函数。 https://perlmaven.com/subroutines-and-functions-in-perl

于 2017-08-24T11:59:34.013 回答
2

f2()from的调用缺少警告f3()似乎是一个错误。

use strict;
use warnings;

f1();

sub f1 {
    my @a = qw(a b c);
    f2(@a);
}

sub f2(\@) { print $_[0] }

这将打印“a”。如果您预先声明f2()或交换子例程定义的顺序,它会打印“ARRAY(0x182c054)”。

至于解决情况,就看情况了。我的偏好(按顺序)是:

  1. 从子例程定义中删除原型。Perl 的原型并没有像大多数人期望的那样做。它们实际上只对声明像内置函数一样的 subs 有用。除非你试图扩展 Perl 的语法,否则不要使用它们。
  2. 在使用子程序之前预先声明它们。这让 Perl 在遇到任何调用之前就知道原型。
  3. 重新排序代码,以便子例程定义出现在任何调用之前。
  4. 使用符号调用子例程&foo()以绕过原型检查。
于 2009-11-12T14:47:35.163 回答
2

如果你要用括号来调用它,你为什么还要使用原型?

sub f1(){ ... }

f1();

我唯一一次使用空原型是用于我想像常量一样工作的子例程。

sub PI(){ 3.14159 }

print 'I like ', PI, ", don't you?\n";

我实际上建议不要使用 Perl 5 原型,除非您希望您的子程序的行为与其他方式不同。

sub rad2deg($){ ... }

say '6.2831 radians is equal to ', rad2deg 6.2831, " degrees, of course.\n";

在此示例中,如果没有原型,则必须使用括号。否则它会得到一个额外的参数,并且最后一个字符串永远不会被打印出来。

于 2009-11-12T16:12:24.103 回答
0

你可以像 C 语言一样先声明它。

sub test($);

test("xx");

sub test($) {
   # do something
}
于 2021-04-28T10:06:00.137 回答