views:

70

answers:

1

It seems that in language like C, Java, and Ruby (as opposed to Javascript), a new scope is created for each iteration of a loop block, and the local variable defined for the loop is actually made into a local variable every single time and recorded in this new scope?

For example, in Ruby:

p RUBY_VERSION

$foo = []

(1..5).each do |i|
  $foo[i] = lambda { p i }
end

(1..5).each do |j|
  $foo[j].call()
end

the print out is:

[MacBook01:~] $ ruby scope.rb
"1.8.6"
1
2
3
4
5
[MacBook01:~] $ 

So, it looks like when a new scope is created, a new local copy of i is also created and recorded in this new scope, so that when the function is executed at a later time, the "i" is found in those scope chains as 1, 2, 3, 4, 5 respectively. Is this true? (It sounds like a heavy operation).

Contrast that with

p RUBY_VERSION

$foo = []

i = 0

(1..5).each do |i|
  $foo[i] = lambda { p i }
end

(1..5).each do |j|
  $foo[j].call()
end

This time, the i is defined before entering the loop, so Ruby 1.8.6 will not put this i in the new scope created for the loop block, and therefore when the i is looked up in the scope chain, it always refer to the i that was in the outside scope, and give 5 every time:

[MacBook01:~] $ ruby scope2.rb
"1.8.6"
5
5
5
5
5
[MacBook01:~] $ 

I heard that in Ruby 1.9, i will be treated as a local defined for the loop even when there is an i defined earlier?

The operation of creating a new scope, creating a new local copy of i each time through the loop seems heavy, as it seems it wouldn't have matter if we are not invoking the functions at a later time. So when the functions don't need to be invoked at a later time, could the interpreter and the compiler to C / Java try to optimize it so that there is no local copy of i each time?

+1  A: 

This is similar to the topic discussed here: http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/ . In some programming languages, when you loop over a variable, the body of the loop construct is bound to one variable that increments. In others, a new loop variable is instantiated per iteration of the loop.

As for lexical scope, note that in JavaScript, functions are the only constructs that form scopes (braces for if, while, for, etc. do not). In C/C++, any pair of braces forms a scope.

Joey Adams