Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
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.


Comment on Re: recursive anonymous subroutines
Select or Download Code
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; }, $_);

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (6)
As of 2014-09-01 22:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite cookbook is:










    Results (17 votes), past polls