From: dblack@... Date: 2006-08-01T21:52:31+09:00 Subject: Re: I thought this was the one that worked? Hi -- On Tue, 1 Aug 2006, Just Another Victim of the Ambient Morality wrote: > > wrote in message > news:Pine.LNX.4.64.0608010732450.7358@rubypal.com... >> >>> wrote in message >>> news:Pine.LNX.4.64.0607312255430.32274@rubypal.com... >>>> >>>> Of course, not all blocks end up getting turned into Proc objects; >>>> some remain just syntactic constructs: >>>> >>>> a = 1 >>>> [1,2,3].each {|x| puts x + a } >>>> >>>> I guess you could debate whether that block is a closure, since it >>>> never leaves the context where it's created -- so there's nothing >>>> really remarkable about the fact that a is still visible inside it. >>>> And every time you put its closureness to the test, so to speak, >>>> you've turned it into a Proc, so technically the Proc, rather than the >>>> block, is the closure. >>> >>> I would debate that it _is_ a closure because, although it's defined >>> where its context is, that's irrelevant. What matters is that the block >>> is >>> passed into the "each" method of the Array class and is executed there, >>> where "a" is not visible. Thus, the block was executed outside of the >>> scope >>> of "a" while still having access to it. How is this possible? It's >>> possible because the block that was passed in is a closure... >>> QED. >> >> It's not exactly passed to the method, though. You can capture it in >> the method -- in which case, it becomes a Proc object, and then >> there's no issue (hair-splitting or otherwise) about its being a >> closure. >> >> If you don't capture it, you can yield to it -- but then you're >> yielding to the block, not calling a Proc object derived from the >> block. > > ...and this would be a problem if the definition of a closure is the > calling of a Proc object derived from a block. Alas, that is _not_ the > definition of a closure... > When we yield to the block, we are doing so in our method, which is > _not_ the same scope as the scope where the block was created. Yet, the > block we're yielding to still has access to that other scope. How? Because > it is a closure... You could say, though, that when you do this: def x a = 1 puts a end def y x end you're calling x from your method y, and x has access to local variables not defined in y, so x must be a closure. > >> It comes down to the fact that blocks are syntactic constructs, while >> Procs are first-class objects. > > I'm not sure why this has anything to do with anything... Consider an if statement: y = 1 if x y end The code in the middle is flat, as regards scope. Furthermore, you can't do anything with it; you can't send that chunk of code somewhere, open it up, and find y. It's just an expression or statement among other expressions or statements. A code block has one foot in that camp. When you see: a = 10 [1,2,3].each {|x| puts x * a } you're seeing, in a sense, a flat scope -- that is, the variable a just gets used, as it might if it were in an if statement. That's only part of the story, though. The other parts are, first, that variables created inside the block are not in scope when the block exits (so its scope is definitely not flat); and, second, the fact that it's so easy to convert a block to a Proc that blocks feel like first-class objects, even though they aren't. David -- http://www.rubypowerandlight.com => Ruby/Rails training & consultancy ----> SEE SPECIAL DEAL FOR RUBY/RAILS USERS GROUPS! <----- http://dablog.rubypal.com => D[avid ]A[. ]B[lack's][ Web]log http://www.manning.com/black => book, Ruby for Rails http://www.rubycentral.org => Ruby Central, Inc.