It doesn't seem evil to me at all, it is exactly what I would expect.
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.
It's the Ruby 1.9 each implementation that seems confusing to me. I don't have a natural feeling about a new scope being created for local variables first referenced in that block. I am much more used to method, object, and class level scoping. In most of the simple Ruby code I write, you can tell the scope of a variable by looking at it's name. I can see where you might need the block scoping with closures, but I actually find the second example more logical. In the first example, I can't imagine which memory address would still be holding the 1, and what it's name would be. I can easily see how the value at i would be 2.
Prints nothing. (Of course, with warnings or strict this complains about both $b and the second $a, as they're either never used or undefined.)
Block scope is very nice. Maybe I don't use enough other OO languages to really grok why you'd want it any other way. What's the benefit to having method rather than block scope in such a context? I don't remember hating not having block scope in Python when I switched for about three or four years, but I didn't really use it in Perl at that point either, so I might miss it now that I do.
Comments
It doesn't seem evil to me at all, it is exactly what I would expect.
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...
Ruby has block local scoping.
It's not the case where you set a beforehand that matters, but when you don't.
For example:
So the real danger comes in here: 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.
It's the Ruby 1.9 each implementation that seems confusing to me. I don't have a natural feeling about a new scope being created for local variables first referenced in that block. I am much more used to method, object, and class level scoping. In most of the simple Ruby code I write, you can tell the scope of a variable by looking at it's name. I can see where you might need the block scoping with closures, but I actually find the second example more logical. In the first example, I can't imagine which memory address would still be holding the 1, and what it's name would be. I can easily see how the value at i would be 2.
To me the following is highly surprising:
I expect "a" to be free outside the loop in Ruby.In most of the OO languages I've used, declaring a variable in a loop header scopes it to the method, not the loop.
Block scope is very nice. Maybe I don't use enough other OO languages to really grok why you'd want it any other way. What's the benefit to having method rather than block scope in such a context? I don't remember hating not having block scope in Python when I switched for about three or four years, but I didn't really use it in Perl at that point either, so I might miss it now that I do.