How are closures implemented?

I’m one of those people who needs to see/understand a typical
implementation of something before I can grok how it works.

How are closures implemented? How does the closure know about its
environment? Since a block can use the various flavors of eval, it seems
to me that the closure needs access to everything.

Seems like magic to me.

I have looked at
http://samdanielson.com/2007/9/6/an-introduction-to-closures-in-ruby but
I am still not grokking it.

Anyone have a link they can recommend on how closures are implemented?

“Any sufficiently advanced technology is indistinguishable from magic.”
Arthur C. Clarke

Ralph S. писал 20.02.2012 12:37:

I’m one of those people who needs to see/understand a typical
implementation of something before I can grok how it works.

How are closures implemented? How does the closure know about its
environment? Since a block can use the various flavors of eval, it
seems to me that the closure needs access to everything.

I would just say that for cases like this:

 def a(x); eval("x"); end

Ruby keeps a list of local variables and its names in runtime and has
an internal method_missing dispatch logic which looks up undefined
methods
in the local variable table.

I wasn’t able to find the relevant source in reasonable time, but the
truth is out there. Someone more familiar with MRI sources than me
could
correct this.

Seems like magic to me.

… and it pretty much is magic.

Ralph S. wrote in post #1047769:

How are closures implemented? How does the closure know about its
environment?

The closure is the environment.

Are you familiar with local variables allocated on a stack? Then instead
imagine stack frames allocated out of the heap, in a linked list.
Instead of being deallocated at the end of a function, they are
garbage-collected when there are no more references to them, just like
any other object.

Robert,

Thursday, February 23, 2012, 6:10:28 AM, you wrote:

On Mon, Feb 20, 2012 at 11:23 PM, Brian C. [email protected]
wrote:

any other object.
This is the best explanation about closures I have read in a long time,
Brian!

Ralph, try this and see whether it helps the explanation sink in:

def f(x)
[
lambda { x += 1 },
lambda { x += 0.5 },
]
end

a, b = f(0)

3.times do
p a.call, b.call
end

Note how there is just a single environment which is shared by the two
closures.

Kind regards

robert

On Thu, Feb 23, 2012 at 4:53 PM, Ralph S. [email protected]
wrote:

]

Is z “on the stack” or “merely” in scope?

I think both.

As I understand it, z is bound to the closure.

Correct.

But how does Ruby know?

z is a local variable in the scope which invokes define_method and
thus visible to the method body because you did not use def which
introduces a completely separate scope and not a nested scope as a
block does. From the scoping perspective your example is no different
than

z = 0

10.times.to_a.each do |y|
z += y
end

The only difference really is that by using define_method you retain
another closure as method body from which the (additionally to
storing the lambdas in a variable after the method call). So you have

  1. closure is the method body and it has access to z because that is
    in the scope visible to the block passed to #define_method.
  2. and 3. closure are the two lambdas returned which access the same z
    also visible to the first closure.

Typically programming language implementations store local variables
on the stack so it does not make a difference whether we are talking
about a method argument or local variable - both would sit on the
stack. For the details you would have to look at the source.

Kind regards

robert

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs