Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

recursive anonymous functions?

12 views
Skip to first unread message

Charles Rendleman

unread,
Sep 4, 2002, 11:12:51 PM9/4/02
to
Is it possible to create an anonymous function that can be used recursively?
ie.

$a = sub { my $x = shift; if ( $x == 1 ) { return 1; } else { return
&THIS_ANONYMOUS_FUNCTION($x-1)*$x; }};

print "fac(10) = ", &$a(10);


--
Charles A. Rendleman http://seesar.lbl.gov/ccse
Center for Computational Sciences and Engineering CARen...@lbl.gov
Lawrence Berkeley National Laboratory phone 510.486.5181
1 Cyclotron Road, MS 50A-1148, Berkeley CA, 94720 fax 510.486.6900

Benjamin Goldberg

unread,
Sep 5, 2002, 1:49:32 AM9/5/02
to
Charles Rendleman wrote:
>
> Is it possible to create an anonymous function that can be used
> recursively?
> ie.
>
> $a = sub { my $x = shift; if ( $x == 1 ) { return 1; } else { return
> &THIS_ANONYMOUS_FUNCTION($x-1)*$x; }};
>
> print "fac(10) = ", &$a(10);

Certainly. Just do the obvious:
my $a;


$a = sub {
my $x = shift;

($x <= 1) ? 1 : $a->($x-1) * $x;
};
print "fac(10) = ", $a->(10), "\n";
__END__

Note, however, that when $a is declared in my(), the name '$a' does not
come into scope until after the statement is complete (that is, until
after the ";"). This means that the following:
my $a = sub {
my $x = shift;
($x == 1) ? 1 : $a->($x-1) * $x;
};
Will *not* work, since $a inside the sub refers to the global $a, rather
than the lexical $a.

--
tr/`4/ /d, print "@{[map --$| ? ucfirst lc : lc, split]},\n" for
pack 'u', pack 'H*', 'ab5cf4021bafd28972030972b00a218eb9720000';

Chris Fedde

unread,
Sep 5, 2002, 1:49:50 AM9/5/02
to
In article <al6i3u$nrs$1...@news.astound.net>,

Charles Rendleman <theren...@astound.net> wrote:
>Is it possible to create an anonymous function that can be used recursively?
>

$f = sub {


my $x = shift;
if ( $x == 1 ) { return 1; }
else {

return $f->( $x - 1 ) * $x;
}
};

print $f->(5)."\n";

Good Luck!
--
This space intentionally left blank

Jay Tilton

unread,
Sep 5, 2002, 7:57:16 PM9/5/02
to
Benjamin Goldberg <gol...@earthlink.net> wrote:

| Charles Rendleman wrote:
| >
| > Is it possible to create an anonymous function that can be used
| > recursively?
|

| Certainly. Just do the obvious:
| my $a;
| $a = sub {
| my $x = shift;
| ($x <= 1) ? 1 : $a->($x-1) * $x;
| };
| print "fac(10) = ", $a->(10), "\n";
| __END__

It's worth mentioning that $a becomes self-referential, and so does not
get GC'ed when it falls out of scope. Make an explicit "undef $a;"
statement when you're done using it. Weakening the reference might be
preferable to remembering the undef.

use WeakRef;


my $a;
$a = sub {
my $x = shift;
($x <= 1) ? 1 : $a->($x-1) * $x;
};

weaken $a;


Brian McCauley

unread,
Sep 6, 2002, 12:21:46 PM9/6/02
to
til...@erols.com (Jay Tilton) writes:

> It's worth mentioning that $a becomes self-referential, and so does not
> get GC'ed when it falls out of scope. Make an explicit "undef $a;"
> statement when you're done using it. Weakening the reference might be
> preferable to remembering the undef.
>
> use WeakRef;
> my $a;
> $a = sub {
> my $x = shift;
> ($x <= 1) ? 1 : $a->($x-1) * $x;
> };
> weaken $a;

It is also worth mentioning that the above won't actually work. :-)

The weaken($a) above simply acts as undef($a) because there are no other
references to the anonymous subroutine.

use Scalar::Util 'weaken';


my $a;
$a = sub {
my $x = shift;
($x <= 1) ? 1 : $a->($x-1) * $x;
};

my $copy_of_a = $a;
weaken $a;

This way the anonymous subroutine is GCed when $copy_of_a goes out of scope.

--
\\ ( )
. _\\__[oo
.__/ \\ /\@
. l___\\
# ll l\\
###LL LL\\

Tramm Hudson

unread,
Sep 6, 2002, 9:03:50 PM9/6/02
to
Benjamin Goldberg <gol...@earthlink.net> wrote:
> Charles Rendleman wrote:
> > Is it possible to create an anonymous function that can be used
> > recursively?
>
> [...]

> Note, however, that when $a is declared in my(), the name '$a' does not
> come into scope until after the statement is complete (that is, until
> after the ";"). This means that the following:
> my $a = sub {
> my $x = shift;
> ($x == 1) ? 1 : $a->($x-1) * $x;
> };
> Will *not* work, since $a inside the sub refers to the global $a, rather
> than the lexical $a.

One way around both this problem is to use a helper that produces the
self reference, although it does require that the function be passed as
the first argument to itself:

my $a = sub {
my $f = shift;
sub { $f->( $f, @_ ) }
}->(
sub {
my ($a,$x) = @_;
($x == 1) ? 1 : $a->($a,$x-1) * $x;
}
);
__END__

Trammell
--
-----|----- hud...@swcp.com H 240-476-1373
*>=====[]L\ hud...@rotomotion.com W 240-453-3317
' -'-`- http://www.swcp.com/~hudson/ KC5RNF

Anno Siegel

unread,
Sep 7, 2002, 4:56:05 PM9/7/02
to
According to Brian McCauley <nob...@mail.com>:

Hmmm... But the subref isn't the thing we want to weaken, is it? (I have
been wrong about the intents and purposes of WeakRef before.) It's the
variable $a which is referenced from within the code and which would be
kept alive after leaving its scope (with no way except the code to access
it). So we would want to weaken a reference to $a, but there is no
(explicit) one. WeakRef doesn't appear to help here.

However, it's probably not worth worrying about. We lose a scalar variable
on a per-routine basis, and I don't see how failure to deallocate it would
lead to a leak. Things may look different when the sub's are generated
dynamically, en masse.

Anno

Jay Tilton

unread,
Sep 7, 2002, 9:08:38 PM9/7/02
to
anno...@lublin.zrz.tu-berlin.de (Anno Siegel) wrote:

| According to Brian McCauley <nob...@mail.com>:

| > The weaken($a) above simply acts as undef($a) because there are no other
| > references to the anonymous subroutine.
| >
| > use Scalar::Util 'weaken';
| > my $a;
| > $a = sub {
| > my $x = shift;
| > ($x <= 1) ? 1 : $a->($x-1) * $x;
| > };
| > my $copy_of_a = $a;
| > weaken $a;
| >
| > This way the anonymous subroutine is GCed when $copy_of_a goes out of scope.
|
| Hmmm... But the subref isn't the thing we want to weaken, is it?

This was my confusion. $a is the thing being weakened, not the coderef.
"weaken $a" just means that $a is not counted as a reference to whatever
is in $a.

"$copy_of_a = $a;" keeps a coderef alive so $a can keep its value.
Without it, $a would be the only coderef, and since it wouldn't count
when weakened, $a would go undef.

Nobull got what I meant, and nailed what I missed.

| (I have been wrong about the intents and purposes of WeakRef before.)

Me too. :)
But I think I get it now.

| However, it's probably not worth worrying about. We lose a scalar variable
| on a per-routine basis, and I don't see how failure to deallocate it would
| lead to a leak. Things may look different when the sub's are generated
| dynamically, en masse.

That's the exact situation I had in mind. Like, say, a closure as a
method for each instance of an object. Could get messy.

0 new messages