开发者

Is it possible to prevent forward undeclared function calls in perl?

Perl has limited support for static code checking, in particular it can check whether we pass appropriate number of argument to a function. For example this will result in error:

use strict;
use warnings;
sub f($) {}
f(2, 3)

Too many arguments for main::f

If we try to call f too early we will get another useful warning:

use strict;
use warnings;
f(2, 3)
sub f($) {}

main::f() called too early to check prototype

This will result in error:

use strict;
use warnings;
sub f($) {}
sub g() { f(2, 3) }

Too many arguments for main::f

And my question is if we can get such message for the following scenario:

use strict;
use warnings;
sub g() { f(2, 3) }
sub f($) {}

Bec开发者_StackOverflow社区ause I do not get any error or warning here. It would be good if I could prevent this code from compiling. Please advise.


"Those in the know" (most notably Damian Conway in his book "Perl Best Practices") advise not to use subroutine prototypes as they only serve to obfuscate code by "making it impossible to deduce the argument-passing behavior of a subroutine call simply by looking at the call."


Do not use prototypes to do argument checks for all the myriad reasons already pointed out. There is temptation to do so because they provide compile-time checks, but their checks are limited to stupid mistakes, they don't check method calls, and they have unexpected side effects.

Use a module such as Method::Signatures to do real argument checking and also provide you with argument processing.

use Method::Signatures;

use strict;
use warnings;

func g() { f(2, 3) }

func f($foo) {
    print "f got $foo\n";
}

The check will happen when the subroutine is run (there's a bug right now where it doesn't check that you passed too many arguments, fixing that) but it gives you a far richer tool set to check your arguments (types coming shortly) than prototypes without all the nasty side effects of prototypes. And it works on method calls, prototypes do not.


Yes you can, by pre-declaring it before you actually use it:

use strict;
use warnings;
sub f($);                     # prototype defined
sub g() { f(2, 3) }
sub f($) { print "hi\n"; }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜