Closures 101

J

jeffperforce

class Object
def singleton_class
class << self
self
end
end
end

data = Object.new
status = "good"
data.singleton_class.class_eval {
define_method:)status) {
status
}
}
p data.status # => "good"
status = "bad"
p data.status # => "bad"

I have a decent amount of experience with ruby, but I have somehow
misunderstood closures this whole time. I thought a closure contained
a full "snapshot" of the stack, but actually it contains references to
the stack. That is, I thought <<status = "bad">> would have no
effect.

This came about from the following situation:

def add_status(array)
index = 0
while index < array.size
status = "running #{index}"
array[index].singleton_class.class_eval {
define_method:)status) {
status
}
}
index += 1
end
end

array = %w(a b c)
add_status(array)
array.each { |elem| p elem.status }
# => "running 2"
# => "running 2"
# => "running 2"

If we replace "while index < array.size" with "array.size.times do"
then we get
# => "running 0"
# => "running 1"
# => "running 2"

So "times" uses a closure which in turn creates a new "status"
variable, whereas the while loop does not use a closure and there is
only one "status".

I haven't encountered this behavior before since I rarely use such
uncouth imperative-style iterations. I'm not sure I have a point, per
se, except that it's possible to use ruby for a long time without
fully understanding closures.
 
D

David A. Black

Hi --

class Object
def singleton_class
class << self
self
end
end
end

data = Object.new
status = "good"
data.singleton_class.class_eval {
define_method:)status) {
status
}
}
p data.status # => "good"
status = "bad"
p data.status # => "bad"

I have a decent amount of experience with ruby, but I have somehow
misunderstood closures this whole time. I thought a closure contained
a full "snapshot" of the stack, but actually it contains references to
the stack. That is, I thought <<status = "bad">> would have no
effect.

I think it's best to think of the closure as preserving a binding. In
that binding, the identifier "status" is bound to "bad". If you
reassign to status, you're changing the binding of status inside the
(overall) binding. The closure continues to reflect that binding.


David
 
R

Robert Dober

Jeff

David explained it very properly. Maybe you might be interested to
read more about it on my blog.
I have written some code that allows to replace ivars with closures
(idea stolen from Tom Christiansen's famous Tom's Object Tutorial in
perl).
This is much slower (about 5 to 10 !!) but might be of interest for
thrade safety and the complete encapsulation (this was Tom's
motivation in the famous TOT)
Anyway it is quite some read ---> http://ruby-smalltalk.blogspot.com/

Cheers
Robert
 
F

fedzor

update your blog!

-------------------------------------------------------|
~ Ari
Some people want love
Others want money
Me... Well...
I just want this code to compile
 
S

Sean Allen

i would guess that they were saying:

good stuff on there.
just not much and nothing recent.

take it as an encore! encore!
 
R

Robert Dober

i would guess that they were saying:

good stuff on there.
just not much and nothing recent.

take it as an encore! encore!

That's very kind of you, but my head is empty and my schedule is full
right now .... :(
Cheers
Robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top