Почему в моем Perl-коде я получаю предупреждения «слишком рано, чтобы проверить прототип»? - PullRequest
11 голосов
/ 12 ноября 2009

У меня есть такой Perl-файл:

use strict;
f1();

sub f3()
{ f2(); }

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

Короче говоря, f1 вызывается до того, как оно будет определено. Итак, Perl выдает предупреждение: «f1 вызван слишком рано, чтобы проверить прототип». Но то же самое относится и к f2, единственное отличие - это то, что он вызывается из другой подпрограммы Не выдает предупреждение за f2. Почему?

Как лучше всего решить эту проблему?

  1. объявить подпрограмму до того, как она будет вызвана
  2. Назовите субмарину так: &f1();

Ответы [ 5 ]

16 голосов
/ 12 ноября 2009

Вы можете полностью избежать этой проблемы, не используя в первую очередь прототипы:

use strict;

f1();

sub f3 { f2() }

sub f1 {}
sub f2 {}

Не используйте прототипы , если вы не знаете, почему вы их используете:

Конечно, все это очень мощно и должно использоваться только в умеренных количествах, чтобы сделать мир лучше.

8 голосов
/ 06 июня 2015

Просто удалите () из ваших определений подпрограммы. Когда вы определяете с помощью (), Perl считает, что это прототипы, и вы должны определить свой прототип, прежде чем использовать его.

Попробуйте это ......

use strict;
f1();

sub f3
{ f2(); }

sub f1
{}
sub f2
{}
2 голосов
/ 24 августа 2017

Когда вы определяете функцию в Perl, вы не должны использовать скобки. Когда вы делаете это, вы получаете эту ошибку. Это неправильно:

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

Это путь:

sub DoSomthing{
   #do what ever...
}

без скобок.

Более подробное объяснение см. На странице Габора Сабо, посвященной Perl Maven, о подпрограммах и функциях в Perl. https://perlmaven.com/subroutines-and-functions-in-perl

2 голосов
/ 12 ноября 2009

Если вы собираетесь назвать это с круглыми скобками, почему вы даже используете прототипы?

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";

В этом примере вам придется использовать круглые скобки, если у него нет прототипа. В противном случае он получил бы дополнительный аргумент, и последняя строка никогда не была бы напечатана.

2 голосов
/ 12 ноября 2009

Отсутствие предупреждения о звонке на f2() с f3() представляется ошибкой.

use strict;
use warnings;

f1();

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

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

Это печатает "а". Если вы либо предварительно объявите f2(), либо поменяете местами порядок определений подпрограмм, будет напечатано «ARRAY (0x182c054)».

Что касается разрешения ситуации, это зависит. Мои предпочтения (по порядку) будут:

  1. Удалить прототипы из определений подпрограмм. Прототипы Perl не делают что большинство людей ожидают от них. Они действительно полезны только для объявления подводных лодок, которые действовать как встроенные. Если вы не пытаетесь расширить синтаксис Perl, не используйте их.
  2. Предварительно объявить подпрограммы перед их использованием. Это позволяет Perl узнать о прототипе до появления каких-либо звонков.
  3. Измените порядок кода, чтобы определения подпрограмм появлялись перед любыми вызовами.
  4. Вызовите подпрограммы, используя нотацию &foo(), чтобы обойти проверку прототипа.
...