Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Ruby has block local scoping.

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.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: