Using Closures

Bill Venners: What makes a block a closure?

Yukihiro Matsumoto: A closure object has code to run, the executable,
and state around the code, the scope. So you capture the environment, namely the local
variables, in the closure. As a result, you can refer to the local variables inside a closure.
Even after the function has returned, and its local scope has been destroyed, the local
variables remain in existence as part of the closure object. When no one refers to the
closure anymore, it's garbage collected, and the local variables go away.

Bill Venners: So the local variables are basically being shared between
the closure and the method? If the closure updates the variable, the method sees it. And if
the method updates the variable, the closure sees it.

Yukihiro Matsumoto: Yes, local variables are shared between the
closure and the method. It's a real closure. It's not just a copy.

Bill Venners: What is the benefit of a real closure? Once I make a block
into an object, what can I do with it?

Yukihiro Matsumoto: You can reconvert a closure back into a block, so
a closure can be used anywhere a block can be used. Often, closures are used to
store the status of a block into an instance variable, because once you convert a block into
a closure, it is an object that can by referenced by a variable. And of course closures can
be used like they are used in other languages, such as passing around the object to
customize behavior of methods. If you want to pass some code to customize a method,
you can of course just pass a block. But if you want to pass the same code to more than
two methods -- this is a very rare case, but if you really want to do that -- you can
convert the block into a closure, and pass that same closure object to multiple methods.

Bill Venners: OK, but what is the benefit of having the context? The
distinction that
makes Ruby's closure a real closure is that it captures the context, the local variables and
so on. What benefit do I get from having the context in addition to the code that I don't get
by just being able to pass a chunk of code around as an object?

Yukihiro Matsumoto: Actually, to tell the truth, the first reason is to
respect the history of Lisp. Lisp provided real closures, and I wanted to follow that.

Bill Venners: One difference I can see is that data is actually shared
between the closure objects and the method. I imagine I could always pass any needed
context data into a regular, non-closure, block as parameters, but then the block would
just have a copy of the context, not the real thing. It's not sharing the context. Sharing is
what's going on in a closure that's different from a plain old function object.

Yukihiro Matsumoto: Yes, and that sharing allows you to do some
interesting code demos, but I think it's not that useful in the daily lives of programmers. It
doesn't matter that much. The plain copy, like it's done in Java's inner classes for
example, works in most cases. But in Ruby closures, I wanted to respect the Lisp culture.

Next Week

Come back Monday, December 29 for part IV of this conversation with Yukihiro Matsumoto.
If you'd like to receive a brief weekly email
announcing new articles at Artima.com, please subscribe to
the Artima Newsletter.

Talk Back!

Have an opinion about the design principles presented in this article?
Discuss this article in the Articles Forum topic,
Blocks and Closures in Ruby.