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

Ruby:如何初始化块变量的值

  •  0
  • ouni  · 技术社区  · 7 年前

    我正在学习Ruby,并输入了一段代码来试验块范围的变量:

    x = 10
    3.times do |i; x|
      x = x + 1
      puts("inside block is #{x}")
    end
    puts("outside block is #{x}")
    

    我希望x block变量自动捕获x全局变量的值,然后块内的x每次为11,块外的x受保护,并保持在10。这种“屏蔽”行为在web上的许多Ruby教程中都有描述。

    但是相反,脚本失败了,它告诉我x为零,并且它没有 +

    这个 准确的 上面的代码在一个名为 delete_me.rb ,运行时使用: ruby delete_me.rb

    运行脚本时,出现以下错误:

    delete_me.rb:3:in `block in <main>': undefined method `+' for nil:NilClass (NoMethodError)
        from delete_me.rb:2:in `times'
        from delete_me.rb:2:in `<main>'
    

    2 回复  |  直到 7 年前
        1
  •  2
  •   user229044    7 年前

    我希望x block变量自动捕获x全局变量的值,

    这不是Ruby的工作方式,也没有理由期望它会这样。内部变量从不从它所隐藏的变量中获取其值 任何 是到 防止 这种事。

    x nil

    如何在Ruby中初始化块变量的值?

    ,然后为其赋值:

    x = 10
    3.times do |i; x|
      x ||= 0
      x = x + 1
      puts("inside block is #{x}")
    end
    puts("outside block is #{x}")
    

    注意,这个循环打印 "inside block is 1" ,三次。你在制造一个新的 并在每次调用块时将其设置为0。如果您想在迭代时累积状态,这是错误的方法。你要么想 给外面罩上阴影 ,或使用其他可枚举方法,如 inject each.with_object .

        2
  •  0
  •   Austio    7 年前

    这是因为在ruby中,块不创建新的作用域,而是在查找表中创建变量。

    x = 10
    3.times do |i; y|
      x = x + 1
      puts("x block is #{x}")
    end
    puts("outside block is #{x}")
    

    或者更好的是,不要用另一个参数来定义它,除非你想覆盖任何全局变量

    x = 10
    3.times do |i|
      x = x + 1
      puts("x block is #{x}")
    end
    puts("outside block is #{x}")
    
    推荐文章