奇怪的Ruby行为

时间:2012-07-17 06:00:02

标签: ruby

考虑以下Ruby代码:

a = ["x"] * 3 # or a = Array.new(3, "x")

a[0].insert(0, "a")
a.each {|i| puts i}

我希望输出为ax,x,x(当然在新行上)。但是,使用Ruby 1.9.1,输出是ax,ax,ax。这是怎么回事?我已将问题缩小到定义数组a的方式。如果我明确写出

a = ["x", "x", "x"]

然后代码按预期工作,但原始代码中的任何一个版本都给了我这种意想不到的行为。似乎* /初始化程序意味着副本实际上是对字符串“x”的同一副本的引用。但是,如果不是我写的插入命令

a[0] = "a" + a[0]

然后我得到了所需的输出。这是一个错误,还是在工作中有一些我不理解的功能?

2 个答案:

答案 0 :(得分:7)

Array.new(size=0, obj=nil)的文档:

  

...它是使用大小 obj 的副本创建的(即 size 引用相同的 obj )。

Array * int

  

...返回通过连接self int 副本构建的新数组

因此,在您惊讶的两种形式中,您最终会得到三个对同一"x"对象的引用,就像您想到的那样。我会说你可能会争论设计决定,但这是一个有记录的故意行为,而不是一个错误。

我知道在不手动编写数组文字(["x", "x", "x"])的情况下获得所需行为的最佳方式是

a = Array.new(3) {"x"}

当然,只有三个元素,它没什么关系,但有了更大的东西,这个形式就派上用场了。

答案 1 :(得分:0)

简而言之,虽然“x”只是一个文字,但它是一个对象。您使用["x'] * 3,因此a包含3个相同的对象。您将'a'插入其中一个,它们将全部更改。