bdenckla has asked for the wisdom of the Perl Monks concerning the following question:
As far as I can tell, Perl cannot detect undefined subroutines at compile time. Is this right? I know Perl can detect undefined symbols of most other types at compile time via "use strict". So, one way around this problem is to use references to anonymous subroutines instead of named subroutines. E.g.,
sub MyFunction { ... }
...
MyFunction();
becomes
my $MyFunction = sub { ... };
...
$MyFunction->();
One consequence of this style is that subroutines must be defined before they are used. This may be considered a good thing or a bad thing.
Another consequence of this style is that it makes stack traces much less meaningful. This is almost certainly a bad thing. Consider the following program.
use Carp qw(cluck); my $f = sub { cluck 'cluck'; }; sub g { cluck 'cluck'; } $f->(); g();
The output of this program is
cluck at ./sub.pl line 9 main::__ANON__() called at ./sub.pl line 12 cluck at ./sub.pl line 8 main::g() called at ./sub.pl line 11
One way around this "__ANON__" problem is to use references to named subroutines rather than references to anonymous subroutines. E.g. the "__ANON__" problem goes away if the program above is modified with the following diff.
< my $f = sub { cluck 'cluck'; };
---
> my $f = \&g;
But, this re-exposes us to the problem of undefined subroutines going undetected at compile time. E.g. above, if the user had accidentally typed "\&G" instead of "\&g", this would go undetected until runtime.
In addition to being error-prone to write and maintain, this solution is cumbersome to read. E.g.
sub MyFunction { ... }
...
MyFunction();
Becomes
my $MyFunction = \&MyFunction;
sub MyFunction { ... }
...
$MyFunction->();
To discourage direct use of named subroutines, some naming convention should probably be used. Perhaps a prefix of "ppp", e.g.
my $MyFunction = \&pppMyFunction;
sub pppMyFunction { ... }
...
$MyFunction->();
In summary, I know of no satsifying solution to this problem. Anybody got any ideas?
Update: Thanks everyone for your replies. Sorry I did not search more carefully before posting; thanks toolic for those very relevant existing posts. It seems like avoiding parentheses and/or using B::Lint are the most promising directions for my purposes.
Update 2: I've added a post to my blog on this topic.
|
|---|