On Procs and Rubies
01 Aug 2009
Recently, I’ve been playing around with Shoes. I ran into an interesting bug (or side affect?) in Ruby 1.8.
Here’s the first code sample, create a Proc for each item in an array, then calling it.
procs = []
[1, 2, 3].each { | x | procs << Proc.new { puts x } }
procs.each { | p | p.call }
# prints 1, 2, 3
Here’s the same code, but adding a local variable of x before calling the block.
x = nil
procs = []
[1, 2, 3].each { | x | procs << Proc.new { puts x } }
procs.each { | p | p.call }
# prints 3, 3, 3
So what happened here? Well, as it turns out, in Ruby 1.8, block variables are not scoped locally to the block. Therefore, when x is evaluated in the Proc, it’s modified in each call. So, when it’s finally called, it’s been changed. This has been fixed in Ruby 1.9. Running the same code in Ruby 1.9 prints 1, 2, 3 for both examples. And now you know.
ruby proc coding horror