从ruby块更改原始变量?

时间:2010-07-16 20:24:08

标签: ruby

  

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

在这个例子中

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

test {|verb| verb = 'something'}

它会打印“没有”。

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

感谢

3 个答案:

答案 0 :(得分:13)

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

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

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

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

这非常直接做你想要的,而且真的是最好的方法。

另一种方法是直接改变传入的对象:

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

我不建议这样做,因为它实际上改变了字符串本身而不是仅仅为变量分配一个新字符串。因此,引用相同字符串对象的其他位置将包含新文本。这不是你的例子中的问题,但它是一个等待在任何真实程序中发生的巨大错误。

答案 1 :(得分:2)

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

如果我怀疑你想根据区块的价值在verb中重新分配test,那么你必须自己做;例如verb = yield verb。但是,块中的赋值在test中仍然没有效果。

答案 2 :(得分:0)

使用String#replace:

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

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