为什么我的Perl代码中出现“过早调用原型”警告?

时间:2009-11-12 05:00:45

标签: perl subroutine

我有一个像这样的Perl文件:

use strict;
f1();

sub f3()
{ f2(); }

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

简而言之,f1在定义之前被调用。因此,Perl发出警告:“f1过早地调用原型”。但f2的情况也是如此,唯一的区别是它是从另一个子程序内部调用的。它不会对f2发出警告。为什么呢?

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

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

6 个答案:

答案 0 :(得分:16)

您可以通过不首先使用原型来完全避免此问题:

use strict;

f1();

sub f3 { f2() }

sub f1 {}
sub f2 {}

Don't use prototypes除非你知道为什么要使用它们:

  

当然,这一切都非常强大,只应在适度的情况下使用才能让世界变得更美好。

答案 1 :(得分:7)

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

试试这个......

use strict;
f1();

sub f3
{ f2(); }

sub f1
{}
sub f2
{}

答案 2 :(得分:2)

来自f2()的{​​{1}}来电时没有发出警告似乎是一个错误。

f3()

打印“a”。如果您预先声明use strict; use warnings; f1(); sub f1 { my @a = qw(a b c); f2(@a); } sub f2(\@) { print $_[0] } 或交换子例程定义的顺序,则会打印“ARRAY(0x182c054)”。

至于解决问题,取决于。我的偏好(按顺序)将是:

  1. 从子例程定义中删除原型。 Perl的原型不行 大多数人都期望他们。它们真的只对声明潜艇有用 像内置的行为。除非您尝试扩展Perl的语法,否则请不要使用它们。
  2. 在使用之前预先说明子程序。这让Perl知道原型 在遇到任何电话之前。
  3. 重新排序代码,以便在任何调用之前显示子例程定义。
  4. 使用f2()表示法调用子程序以绕过原型检查。

答案 3 :(得分: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";

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

答案 4 :(得分:2)

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

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

这是要走的路:

sub DoSomthing{
   #do what ever...
}

没有括号。

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

答案 5 :(得分:0)

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

sub test($);

test("xx");

sub test($) {
   # do something
}