代码之家  ›  专栏  ›  技术社区  ›  nonopolarity

在每次在循环块中创建新作用域的语言中,每次在新作用域中都会创建本地循环变量的新本地副本?

  •  2
  • nonopolarity  · 技术社区  · 14 年前

    似乎在C语言、Java语言和露比语言中(相对于JavaScript),为循环块的每个迭代创建了一个新的范围,并且为循环定义的局部变量实际上是每一次都变成一个局部变量,并记录在这个新的范围内。

    例如,在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
    

    打印输出为:

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

    因此,当创建新的作用域时,它看起来像 i 也会在这个新的作用域中创建和记录,以便在稍后执行函数时,在这些作用域链中分别发现“i”为1、2、3、4、5。这是真的吗?(这听起来像是一次沉重的手术)。

    把它和

    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
    

    这次, 是在进入循环之前定义的,因此Ruby1.8.6不会将此 在为循环块创建的新作用域中,因此当 在范围链中查找,它始终引用 这是在外部范围内的,每次给出5个:

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

    我在Ruby1.9中听说, 将被视为循环的本地定义,即使存在 之前定义的?

    创建新作用域、创建新的本地副本的操作。 循环中的每一次似乎都很重,因为如果我们以后不调用函数似乎就没有关系了。因此,当以后不需要调用函数时,解释器和编译器可以对C/Java进行优化,以使其没有本地副本。 每一次?

    1 回复  |  直到 9 年前
        1
  •  1
  •   Joey Adams    14 年前

    这与此处讨论的主题类似: http://math.andrej.com/2009/04/09/pythons-lambda-is-broken/ . 在某些编程语言中,当循环一个变量时,循环体结构被绑定到一个递增的变量。在其他情况下,每次循环迭代都会实例化一个新的循环变量。

    至于词法范围,请注意,在javascript中,函数是构成范围的唯一构造(括号 if , while , for 等等,不要)。在C/C++中,任何一对支撑形成一个作用域。