On 8/1/06, Chad Perrin <perrin / apotheon.com> wrote: > Specifically, it sounds like what you're saying here would indicate that > this is a closure: > > def foo > bar = 0 > lambda { puts bar += 1 } > end > > baz = foo > > and this is a closure: > > def foo > lambda { puts "Hellow world!" } > end > > bar = foo Yes, this is exactly the point we've been trying to get across. Both of these are closures. > but this is not a closure: > > foo = 0 > > foo.each do > puts bar += 1 > end This is where we get into what David Black described as hair splitting. Lets move away from each, and to a set of more general methods: greeting = "Hello" # 1) explicit proc def foo(callback) callback.call("world") end callback = lambda{ |arg| puts "#{greeting}, #{arg}!" } foo(callback) # prints "Hello, world!" # 2) block converted to proc def bar(&callback) callback.call("world") end bar{ |arg| puts "#{greeting}, #{arg}!" } # prints "Hello, world!" # 3) block yielded to def baz yield "world" end baz{ |arg| puts "#{greeting}, #{arg}!" } # prints "Hello, world!" The first example obviously uses a closure. While true that the environment where "greeting" is defined never goes out of scope, it is not visible within the context where callback is actually executed. The second example performs the exact same operation as the first, the only difference is the syntax and *when* the chunk of code becomes a proc. The third example simply removes the explicit conversion from a block to a proc, using yield instead. As such, the semantics between all three are similar and example three can be arguably said to use a closure as well. This is the stance Gennady and "the Victim" are taking. 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. 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. Jacob Fugal