Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re^2: Is it possible to create a sub exclusive to a sub? (Leak free solution)

by ihb (Deacon)
on Sep 19, 2004 at 11:44 UTC ( [id://392170]=note: print w/replies, xml ) Need Help??


in reply to Re: Is it possible to create a sub exclusive to a sub?
in thread Is it possible to create a sub exclusive to a sub?

With regards to the memory leak issue in Re^2: Is it possible to create a sub exclusive to a sub? (nasty memory leak) I thought I also should suggest a solution for those recursive subroutines that need to be a closure because it needs access to its lexical surrounding.

First I want to emphasize that this is only needed when you need the recursive subroutine to have access to the lexical surrounding. I've very rarely needed that, and my personal style if I need a wrapper subroutine &foo (to e.g. supply default arguments to accumulators ) is to is to just name the recursive subroutine that does the work &_foo_rec.

If you do as in Re: Is it possible to create a sub exclusive to a sub? but using a global datatype you don't create a circular reference. The problem with this solution is that the subroutine won't work right outside the lexical scope it was created in, something that's rarely needed for the problem you're solving above. If you both need to access the lexical surrounding and need to use it outside its lexical surrounding you can do the bit cumbersome

use vars qw/ $REC /; my $_foo = sub { ... ; ... $REC->(...) ... ; ... ; }; my $foo = sub { local $REC = $_foo; $_foo->(@_); };
and use $fac however you like from wherever you like. The $_foo subroutine is the actual subroutine but to make it safe and always work you need to first set $REC before calling it. That's what the wrapper subroutine in $foo is for.

If you don't need to use the recursive subroutine outside its lexical scope you can do any of the following:

sub foo { no warnings 'redefine'; local *foo = sub { ... ; ... foo(...) ...; ... ; }; return foo(@_); }
This redefines the subroutine itself and that should be OK since the recursive subroutine probably never wants to use the wrapper subroutine. If this isn't good enough you may use
use vars qw/ $REC /; sub foo { local $REC = sub { ... ; ... $REC->(...) ...; ... ; }; return $REC->(@_); }
which is totally safe. As you see, you may have a reused global variable called $REC or whatever that you always use for the local recursive subroutines.

The last suggestion above brings the thought to a favourite of mine: &_!

sub foo { no warning 'redefine'; # needed if the recursive sub calls any + other sub local *_ = sub { ... ; ... _(...) ...; ... ; }; return _(@_); }
To my great joy Larry realized the coolness of having a "current subroutine subroutine" and &_ will automagically be available for all subroutines in Perl 6!

Update: Added solution for subroutines that both need to access the lexical surrounding and need to be used outside its lexical surrounding.

ihb

Read argumentation in its context!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://392170]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (5)
As of 2024-04-25 10:01 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found