jonathansamuel has asked for the wisdom of the Perl Monks concerning the following question:

The following fails to pass 'use warnings.' It generates the warning "/turnoff8.pl:20: main::check_ip() called too early to check prototype." Is there a way to use both recursion and 'use warnings'?
sub check_ip() { eval{ my $ip_test = new Net::IP(`curl whatismyip.org`); return $ip_test->ip(); }; if ($@){ sleep(300); check_ip(); }; }

Replies are listed 'Best First'.
Re: Is recursion consistent with "use warnings"
by CountZero (Bishop) on Apr 09, 2010 at 05:58 UTC
    Drop the () in your subroutine definition and the warning will go away.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      As CountZero suggested, I removed the parentheses from the sub declaration and 'use warnings' no longer chirps. Thanks.
Re: Is recursion consistent with "use warnings"
by tilly (Archbishop) on Apr 09, 2010 at 06:17 UTC
    Prototypes are a horrible idea. Still if you want to make that mistake you can by predeclaring the function so that inside the function it knows the prototype:
    sub check_ip(); sub check_ip() { eval{ my $ip_test = new Net::IP(`curl whatismyip.org`); return $ip_test->ip(); }; if ($@){ sleep(300); check_ip(); }; }
Re: Is recursion consistent with "use warnings"
by JavaFan (Canon) on Apr 09, 2010 at 10:48 UTC
    The issue is that a prototype only gets associated with the subroutine after it has finished compiling; so by the time the compiler encounters the check_ip() inside the sub, it knows that check_ip() has a prototype, but it doesn't know which one yet.

    As suggested by other posters, either drop the prototype (which doesn't buy you anything in the way you're using it), or declare the sub before defining it.

    Note however that you still may get a warning - if your eval keeps failing, you'll hit a trigger that warns you for possible infinite recursion. Your sub is easily coded without recursion:

    sub check_ip { { my $ip = eval { # Indirect object calls are so last millenium Net::IP->new(`curl whatismyisp.org`)->ip; }; return $ip if defined $ip; sleep 300; redo; } }
    Of course, one can easily make a loop using while (or until), or even a goto as well.