Trade a little anonymity for expressivity. Despite the apparently oxymoronic name, "named anonymous subroutines" are an undocumented feature of Perl. Originally described by "ysth" on Perl Monks, these are a wonderful feature. Suppose your program merrily runs along with a carefree attitudebut then dies an ugly death: Denominator must not be zero! at anon_subs.pl line 11 main::__ANON__(0) called at anon_subs.pl line 17 What the heck is main::__ANON__(0)? The answer may be somewhere in code such as: use Carp; sub divide_by { my $numerator = shift; return sub { my $denominator = shift; croak "Denominator must not be zero!" unless $denominator; return $numerator / $denominator; }; } my $seven_divided_by = divide_by(7); my $answer = $seven_divided_by->(0); In this toy example, it's easy to see the problem. However, what if you're generating a ton of those divide_by subroutines and sending them all throughout your code? What if you have a bunch of subroutines all generating subroutines (for example, if you've breathed too deeply the heady fumes of Mark Jason Dominus' Higher Order Perl book)? Having a bunch of subroutines named __ANON__ is very difficult to debug.
The HackCreating an anonymous subroutine creates a glob named *__ANON__ in the current package. When caller( ) and the rest of Perl's guts look for names for anonymous subroutines, they look there. Using carp and croak will quickly reveal this. The solution is therefore to override this name temporarily. The easy way is to have the parent subroutine name the anonymous one: sub divide_by { my $numerator = shift; my $name = (caller(0))[3]; return sub { local *__ANON__ = "__ANON__$name"; my $denominator = shift; croak "Denominator must not be zero!" unless $denominator; return $numerator / $denominator; }; } Running the program now produces the output: Denominator must not be zero! at anon_subs.pl line 12 __ANON__main::divide_by(0) called at anon_subs.pl line 18 Hacking the HackWhile that's better and it may fit your needs, it's not the most flexible solution. If you create several anonymous subroutines, they will all have the same name. It's more powerful to name the anonymous subroutines by passing the creator subroutine a nameor taking it from an argument, as appropriate. use Carp; sub divide_by { my ($name, $numerator) = @_; return sub { local *__ANON__ = "__ANON__$name"; my $denominator = shift; croak "Denominator must not be zero!" unless $denominator; return $numerator / $denominator; }; } my $three_divided_by = divide_by( 'divide_by_three', 3 ); my $answer = $three_divided_by->(0); The output looks like you expect: Denominator must not be zero! at anon_subs.pl line 12 __ANON__main::divide_by_three(0) called at anon_subs.pl line 18
|