Problems? Is your data what you think it is? PerlMonks

### Re: recursive anonymous subroutines

by snoopy (Deacon)
 on Apr 07, 2006 at 01:30 UTC ( #541775=note: print w/replies, xml ) Need Help??

in reply to recursive anonymous subroutines

What's wrong storing a reference to an anonymous inner sub in an anonymous outer closure?

Eg to create an recursive factorial subroutine:

```#!/usr/bin/perl

use strict;

my \$sub = do {
my \$this_sub;

\$this_sub = sub {
my \$factor = int(shift);
return \$factor > 1
? &\$this_sub(\$factor-1) * \$factor
: 1;
};

};

print "factorial of 7 is ".&\$sub(7)."\n";
This is localised and lends itself to functional usage, eg:
```my @factorials = map {&{
my \$this_sub;

\$this_sub = sub {
my \$factor = int(shift);
return \$factor > 1
? &\$this_sub(\$factor-1) * \$factor
: 1;
}}(\$_)} (3,5,7,9);

print "factorials: @factorials\n";
Update: see below for revised solution.

Replies are listed 'Best First'.
Re^2: recursive anonymous subroutines
by Anonymous Monk on Apr 08, 2006 at 21:51 UTC
"What's wrong storing a reference to an anonymous inner sub in an anonymous outer closure?"
It's a recursive, i.e. leaking, reference.
It's a recursive, i.e. leaking, reference.

Hmm... probably safer to keep the reference on the call stack, thus releasing it on exit.

For example, adopting the convention that the reference is always passed as the first parameter:

```my @factorials = map {

\$_[0] ||= sub {
my \$factor = pop;

return \$factor > 1
? &{\$_[0]}(\$_[0],\$factor-1) * \$factor
: 1;
};

&{\$_[0]}(\$_[0],\$_)} (3,5,7,9);
..or..
```sub make_call {
goto \$_[0];
}

my @factorials = map {

make_call (sub {
my \$factor = \$_[1];

return \$factor > 1
? make_call(\$_[0], \$factor-1) * \$factor
: 1;
}, \$_);

} (3,5,7,9);
Very nice! I believe your make_call version will shortly become a new idiom in my code. Many thanks!
Just thought I'd point out that this is an interesting reinvention of a previous post (though with one less level into the call stack due to the goto). Compare:
```# Your's:
sub make_call { goto \$_[0] }

# Anonymonk's(slightly rearranged):
sub Y { \$_[0]->(@_) }
Update: Well, it's more the same if you change your call to:
```make_call (sub {
my \$factor = \$_[1];

return \$factor > 1
? \$_[0]->(\$_[0], \$factor-1) * \$factor
: 1;
}, \$_);

Create A New User
Node Status?
node history
Node Type: note [id://541775]
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (5)
As of 2018-03-22 22:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
When I think of a mole I think of:

Results (286 votes). Check out past polls.

Notices?