Closures in Ruby

Posted by Isaac Cambron on Stack Overflow See other posts from Stack Overflow or by Isaac Cambron
Published on 2010-05-14T02:16:25Z Indexed on 2010/05/14 2:24 UTC
Read the original article Hit count: 269

Filed under:
|

I'm kind of new to Ruby and some of the closure logic has me a confused. Consider this code:

array = []
for i in (1..5)
  array << lambda {j}
end
array.map{|f| f.call} => [5, 5, 5, 5, 5]

This makes sense to me because i is bound outside the loop, so the same variable is captured by each trip through the loop. It also makes sense to me that using an each block can fix this:

array = []
(1..5).each{|i|  array << lambda {i}}
array.map{|f| f.call} => [1, 2, 3, 4, 5]

...because i is now being declared separately for each time through. But now I get lost: why can't I also fix it by introducing an intermediate variable?

array = []
for i in 1..5
  j = i
  array << lambda {j}
end
array.map{|f| f.call} => [5, 5, 5, 5, 5]

Because j is new each time through the loop, I'd think a different variable would be captured on each pass. For example, this is definitely how C# works, and how -- I think-- Lisp behaves with a let. But in Ruby not so much. It almost looks like = is aliasing the variable instead of copying the reference, but that's just speculation on my part. What's really happening?

© Stack Overflow or respective owner

Related posts about ruby

Related posts about closures