It's nice that James managed to dig up some technical reasons that extend beyond the idiomatic argument, as it may help push along those who aren't moved merely by the "It's not the Ruby way" argument.
Either way, there is at least one case where the custom block iterator doesn't cover the usage of "for" - where you need the variables outside the scope of the loop.
a = 1
for a in 1..2
b = a
end
p a
>> 2
It seems natural that that would change the value of "a", I wouldn't expect a for loop to create a new scoping context. The example with putting a closure into the array is also what I would expect.I am not sure what programming language has the scoping rules he expects, but for me there's nothing to see here, moving along...
It's not the case where you set a beforehand that matters, but when you don't.
For example:
>> (1..2).each { |i| p i }
1
2
=> 1..2
>> i
NameError: undefined local variable or method `i'
>> for i in 1..2; p i; end
1
2
=> 1..2
>> i
=> 2
So the real danger comes in here: >> procs = []
=> []
>> (1..2).each { |i| procs << lambda { i } }
=> 1..2
>> procs.map { |e| e.call }
=> [1, 2]
>> procs2 = []
=> []
>> for i in 1..2; procs2 << lambda { i }; end
=> 1..2
>> procs2.map { |e| e.call }
=> [2, 2]
Which seems better to you?If you're not coming from Ruby, I can understand how reading the first part of this entry might make you think "what's the big deal", but if you read on, you'll see an extended version of what I've shown above.
It's the closures that make this issue complicated.
#assuming a is unbound at this point
for a in 1..2
b = 2
end
p a
>> 2
I expect "a" to be free outside the loop in Ruby.Edit: I mean in
each { |i| p i }
the |i| stands for a shorthand lambda, that binds an i.And in
for i in 1..3
p i
end
there is no such binding. So where's the problem? That 'for' should use a lambda?