Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting "called too early to check prototype" warnings in my Perl code?

I have a Perl file like this:

use strict;
f1();

sub f3()
{ f2(); }

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

In short, f1 is called before it is defined. So, Perl throws a warning: "f1 called too early to check prototype". But same is the case with f2, the only diff being that it is called from inside another subroutine. It doesn't throw a warning for f2. Why?

What is the best way to resolve this issue?

  1. declare the subroutine before it is called
  2. call the sub like this: &f1();
like image 821
user65457 Avatar asked Nov 12 '09 05:11

user65457


4 Answers

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.

like image 53
Sinan Ünür Avatar answered Nov 15 '22 19:11

Sinan Ünür


Simply remove the () from your subroutine definitions. When you define with (), Perl thinks these are prototypes and you have to define your prototype before you use it.

Try this:

use strict;
f1();

sub f3
{ f2(); }

sub f1
{}
sub f2
{}
like image 30
harleygolfguy Avatar answered Nov 15 '22 18:11

harleygolfguy


When you define a function in Perl you should not use parentheses. When you do so you get this error. This is wrong:

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

This is the way to go:

sub DoSomthing{
   #do what ever...
}

no parentheses.

For more detailed explenation see Gabor Szabo's Perl Maven page on Subroutines and functions in Perl. https://perlmaven.com/subroutines-and-functions-in-perl

like image 4
Adam Borenstien Avatar answered Nov 15 '22 19:11

Adam Borenstien


The lack of a warning on the call to f2() from f3() appears to be a bug.

use strict;
use warnings;

f1();

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

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

This prints "a". If you either predeclare f2() or swap the order of the subroutine definitions, it prints "ARRAY(0x182c054)".

As for resolving the situation, it depends. My preferences (in order) would be:

  1. Remove the prototypes from the subroutine definitions. Perl's prototypes don't do what most people expect them to. They're really only useful for declaring subs that act like builtins. Unless you're trying to extend Perl's syntax, don't use them.
  2. Predeclare the subroutines before using them. This lets Perl know about the prototype before the encountering any calls.
  3. Reorder the code so that the subroutine definitions appear before any calls.
  4. Call the subroutines using the &foo() notation to bypass prototype checking.
like image 2
Michael Carman Avatar answered Nov 15 '22 19:11

Michael Carman