J
jeffperforce
class Object
def singleton_class
class << self
self
end
end
end
data = Object.new
status = "good"
data.singleton_class.class_eval {
define_methodstatus) {
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_methodstatus) {
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.
def singleton_class
class << self
self
end
end
end
data = Object.new
status = "good"
data.singleton_class.class_eval {
define_methodstatus) {
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_methodstatus) {
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.