From: Logan Capaldo Date: 2006-08-01T09:57:03+09:00 Subject: Re: I thought this was the one that worked? On Jul 31, 2006, at 7:07 PM, Chad Perrin wrote: > On Tue, Aug 01, 2006 at 07:54:33AM +0900, Jacob Fugal wrote: >> On 7/31/06, Chad Perrin wrote: >>> On Tue, Aug 01, 2006 at 07:05:31AM +0900, Logan Capaldo wrote: >>>> I'm not sure I understand your question. All blocks (by blocks I >>>> mean >>>> do / end and { } ) are (lexically scoped) closures. >>> >>> I'll use a Perl example: >>> >>> sub foo { >>> my $bar = 1; >>> return sub { print ++$bar }; >>> } >>> >>> my $baz = foo(); >>> >>> Voila. $baz contains a lexical closure. This is the case >>> because the >>> return value from foo() was lexically "closed" by virtue of $bar >>> going >>> out of scope, but its value still being accessible via the coderef >>> returned from foo() and assigned to $baz. >> >> How is this different from: >> >> def foo >> bar = 1 >> return proc{ bar += 1; puts bar } >> end >> >> begin >> puts bar >> rescue Exception => e >> puts e >> end >> # => undefined local variable or method `bar' for main:Object >> >> baz = foo >> baz.call # => 2 >> baz.call # => 3 >> baz.call # => 4 > > Who said it's different? I'm just asking about the foregoing > statement > that all blocks are closures (which strikes me as improbable). That's > like saying that this will generate a closure (which it won't): > > sub foo { > return sub { my $bar = 1; print ++$bar }; > } > In ruby it does. I'm having difficulty thinking of a simple example to demonstrate it, but basically it grabs the whole environment whether theres a reference to a variable or not. It does this to allow things like: def foo x = 1 lambda { puts eval("X".downcase) } end You might say, so it just notices that you're using eval. But consider this: def bar x = 1 lambda { puts send("lave".reverse, "y".sub(/y/, 'x')) } end Obviously contrived examples, but this is part of the reason blocks "leak" memory. > -- > CCD CopyWrite Chad Perrin [ http://ccd.apotheon.org ] > print substr("Just another Perl hacker", 0, -2); >