使用带有局部变量的`times`块有奇怪的行为

时间:2013-01-05 04:36:21

标签: ruby block

我试图整理一种方法来重复单词或短语t次。我找到了一个更好的方法,但仍然不确定为什么这个表现得像它一样。

# repeats the word s t times for a default of 2
def repeat s, t = 2
    say = s
    t -= 1
    t.times { say << ' ' + s }
    say
end

repeat('hi', 1) # => 'hi'
repeat('hi', 2) # => 'hi hi'
repeat('hi', 3) # => 'hi hi hi hi' [4x]
repeat('hi', 4) # => 'hi hi hi hi hi hi hi hi' [8x]
repeat('hi', 5) # => 'hi hi hi hi hi hi hi hi hi hi hi hi hi hi hi hi' [16x]

times块内,似乎s在每次迭代后被设置为与say相同的东西。为什么会出现这种情况?

2 个答案:

答案 0 :(得分:3)

在作业say = s中,Ruby不会将s的值分配给say,而是将s的引用(内存位置)分配给s。也就是说,saysay << ' ' + s指向内存中的相同字符串。然后,在行' ' + s中,Ruby首先创建一个具有连接say值的新字符串,然后将其附加到say指向的字符串。由于ss指向相同的字符串,s也会更改。

这与您刚用say替换所有{{1}}基本相同。

请参阅@AJcodez的答案,了解其替代方案,以实现您的目标。

答案 1 :(得分:2)

原因是字符串的铲运算符<<将内容附加到字符串本身,当您指定say = s时,@iamnotmaynard指出您正在分配引用。

为了更好地说明,以下修改使repeat按照您的意图行事:

say = s.dup   # make an actual copy

或者您可以使用+=代替<<每次构建一个新字符串(不指向s

t.times { say += ' ' + s }