【问题标题】:change the original variable from a ruby block? [duplicate]从红宝石块更改原始变量? [复制]
【发布时间】:2011-03-17 03:57:43
【问题描述】:

可能重复:
'pass parameter by reference' in Ruby?

在这个例子中:

def test
  verb = 'nothing'
  yield verb
  puts verb
end

test {|verb| verb = 'something'}

它将打印“无”。

是否可以将其更改为“某物”?

谢谢

【问题讨论】:

    标签: ruby


    【解决方案1】:

    在您的函数中,yield verb 将返回评估块的结果。块中的verb 变量与test 中的变量不同;它们是不同范围内的不同变量。在 Ruby 中,赋值是一个表达式,因此评估您的块会产生“某事”,但您不会对从 yield 返回的值做任何事情。

    我怀疑,如果您想根据块的值在test 中重新分配verb,您必须自己做;例如verb = yield verb。但是,块中的分配在test 中仍然无效。

    【讨论】:

      【解决方案2】:

      使用字符串#replace:

      def test
        verb = 'nothing'
        yield verb
        puts verb
      end
      
      test {|verb| verb.replace('something')}
      

      【讨论】:

        【解决方案3】:

        您必须记住,Ruby 中的变量只是对对象的引用。每个引用都独立于任何其他引用,尽管它们可能引用同一个对象。

        要记住的另一件事是块的范围是它在其中定义的范围。因此,对于您的块,verb 不在范围内(因为它是在 verb 所在的方法外部定义的)。

        除了 stephenjudkins 提到的 eval-binding hack 之外,还有两种方法可以做你想做的事。一种就是分配verb

        def test
          verb = 'nothing'
          verb = yield verb
          puts verb
        end
        

        这很直接地做你想要的,确实是最好的方法。

        另一种方式是直接对传入的对象进行变异:

        test {|verb| verb.replace 'something'}
        

        不过,我不推荐这样做,因为它实际上会更改字符串本身,而不是仅仅为变量分配一个新字符串。因此,引用相同字符串对象的其他地方,它将包含新文本。在您的示例中这不是问题,但它是一个等待在任何实际程序中发生的巨大错误。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-04-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多