From: Logan Capaldo Date: 2006-08-01T11:43:32+09:00 Subject: Re: I thought this was the one that worked? On Jul 31, 2006, at 10:18 PM, Chad Perrin wrote: > On Tue, Aug 01, 2006 at 09:57:03AM +0900, Logan Capaldo wrote: >> On Jul 31, 2006, at 7:07 PM, Chad Perrin wrote: >> >>> 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. > > Um, no . . . that's not the equivalent of what I just posted. To make > it equivalent, you'd have to do something like this: > > def foo > lambda { x = 1; puts eval("X".downcase) } > end > It's still a closure. Like I said it's hard to give you an example, but ruby creates a closure for a block regardless. That lambda still has a reference to the enclosing scope of foo, even if their are no variables there. Ok I came up with a good one: % cat closure2.rb class A def initialize @a = 1 end def foo lambda { puts @a } end def set_var(val) @a = val end end a = A.new baz = a.foo baz.call a.set_var( "Hello" ) baz.call % ruby closure2.rb 1 Hello In this case it happens to be closing over "self", but since this is ruby there is _always_ a self, all blocks are closures. (and you always have the associated overhead) > -- > CCD CopyWrite Chad Perrin [ http://ccd.apotheon.org ] > print substr("Just another Perl hacker", 0, -2); >