From: Jacob Fugal Date: 2006-08-03T00:46:16+09:00 Subject: Re: I thought this was the one that worked? On 8/1/06, Just Another Victim of the Ambient Morality wrote: > "Jacob Fugal" wrote in message > news:507567670608011256r43f08bd5w3f5a43b00d80df32@mail.gmail.com... > > > > # 3) block yielded to > > def baz > > yield "world" > > end > > > > David's point, however, is that in the third example, when yield is > > used instead of converting it to a block, the code inside the block > > never really leaves the context in which it is created, because of the > > way non-converted blocks are implemented. More specifically, that > > implementation doesn't need to store that environment. This is a > > probable reason for the speed difference between converted blocks > > (first class procs) and unconverted blocks (yield). Since the > > environment is never stored, it's not really a closure *in the > > implementation*. This is the hair that David was splitting. > > Maybe you know more about the implementation of blocks than I do but I > find it hard to believe that yielded blocks don't store a reference to their > environment. I mean, they were able to access it, right? How does it do > that without that reference? The way I imagine it (I haven't looked at the C, so I could be -- and probably am -- way off, but this is how I might make a first stab at implementing it) is that when a method is called with a non-converted block, that block never leaves its creation point. It is not wrapped up in any representation, except maybe a few variables *within* (not referring to) the calling context. When yield is encountered in the method body, execution is bumped back up into the calling context where the block is executed, then when the block returns we pop back into the current context of the method. So when the block is executed, it has access to the context where it was created because it's being executed *in* the context where it was created. This is obviously not what is really happening, since -- for instance -- variables first assigned to within the block do not persist within that blocks creating context after the block terminates. It should be close enough, though, to show how the block can access its creating context without needing a reference to it. > > But semantically, whether a block is converted to a proc or just > > yielded to, the behavior regarding variable scope is identical; so if > > one is a closure, it's useful to refer to the other as a closure as > > well, even if it's not implemented as a true closure. In this sense, > > all blocks are closures. > > I believe that, when describing a programming language and its features, > the behaviour of the language is more important than its implementation. I > mean, the language is defined by its specification rather than some > implementation, right? Agreed. You'll find me in the camp that claims all blocks are closure for all practical purposes. Mostly, I was just trying to figure out myself what David might have been referring to in his hair-splitting comments, since I respect him a great deal and expect him to know much more about Ruby internals than I do. :) Jacob Fugal