What if you want to write a recursive subroutine but you don’t know the name of the current subroutine? Since Perl is a dynamic language and code references are first class objects, you might not know the name of the code reference, if it even has a name. Perl 5.16 introduces __SUB__ as a special sequence to return a reference to the current subroutine. You could almost do the same thing without the new feature, but each of those have drawbacks you might want to avoid.
Although __SUB__ looks like __FILE__, __LINE__, and __PACKAGE__, each of which are compile-time directives, the __SUB__ happens at run time so you can use it with subroutines you define later.
First, consider how you’d try to do this without the __SUB__ feature. You could declare a variable to hold a subroutine reference then in a later statement define the subroutine. Since you’ve already declared the variable, you can use it in the definition. Perl won’t de-reference it until you actually run the subroutine, so it doesn’t matter that it’s not a reference yet:
use v5.10;
my $sub;
$sub = sub {
state $count = 10;
say $count;
return if --$count < 0;
$sub->();
};
$sub->();
Your output is a countdown:
10 9 8 7 6 5 4 3 2 1 0
To do that, there are two requirements: the code reference must be stored in a variable, and the variable must already be defined. That’s not always convenient. Not only that, your anonymous subroutine contains a reference to itself, so you’d either have to play games with weak references or just let the reference live forever. Neither of those are attractive.
Rafaël Garcia-Suarez solved these problems by creating Sub::Current to give you a ROUTINE function that returns a reference to the current subroutine, even if it is a named subroutine:
use v5.10;
use Sub::Current;
sub countdown {
state $count = 10;
say $count;
return if --$count < 0;
ROUTINE->();
};
countdown();
You might want to define these code references as a single statement, even you don’t need to. This is useful for inline subroutines where you want to define the code reference in the parameter list:
use v5.10;
use Sub::Current;
sub run { $_[0]->() };
run( sub {
state $count = 10;
say $count;
return if --$count < 0;
ROUTINE->();
}
);
You may want to define the subroutine in one statement as a return value:
use v5.10;
use Sub::Current;
sub factory {
my $start = shift;
sub {
state $count = $start;
say $count;
return if --$count < 0;
ROUTINE->();
}
};
factory(4)->();
Using this module has the disadvantage of a CPAN dependency, although a very light one because it’s self contained. There’s another module, Devel::Caller, from Richard Clamp that can can get a code reference from any level in the call stack, including the current level:
use v5.10;
use Devel::Caller qw(caller_cv);
sub factory {
my $start = shift;
sub {
state $count = $start;
say $count;
return if --$count < 0;
caller_cv(0)->();
}
};
factory(7)->();
Perl 5.16 lets you do the same thing without the CPAN module:
use v5.15.6; # until v5.16 is released
sub factory {
my $start = shift;
sub {
state $count = $start;
say $count;
return if --$count < 0;
__SUB__->();
}
};
As with many new features added since Perl v5.10, you can enable __SUB__ with a use VERSION statement,
as you see in the previous example, or with the feature pragma and the current_sub import:
use feature qw(say state current_sub);
sub factory {
my $start = shift;
sub {
state $count = $start;
say $count;
return if --$count < 0;
__SUB__->();
}
};
factory(7)->();
Things to remember
- Perl v5.16 provides the
__SUB__directive to return a reference to the currently running subroutine - Import this new feature by requiring the Perl version or through
thefeaturepragma - Prior to Perl v5.16, you can do this the same thing with Sub::Current

0 Comments.