Ruby 奇怪的红宝石行为
考虑以下Ruby代码:Ruby 奇怪的红宝石行为,ruby,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"] 然后代码按预期工作,但是原始代码中的任何一个版本都给了我这种意外的行为。看起来*/初始值设定项意味着副本实际上是
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的同一副本的引用。但是,如果我编写的不是insert命令,而是
a[0] = "a" + a[0]
然后我得到所需的输出。这是一个bug,还是我不了解工作中的某些功能?文档:
。。。它是使用obj的大小副本创建的,即对同一obj的大小引用
以及:
。。。返回通过连接self的int副本生成的新数组
因此,在这两种形式中,您都会感到惊讶,最终会得到对同一个x对象的三个引用,正如您所发现的。我想说,您可能会对设计决策提出异议,但这是一种有记录的故意行为,而不是bug
我所知道的在不手动写入数组文本[x,x,x]的情况下获得所需行为的最佳方法是
当然,只要有三个元素,就没什么大不了的了,但是如果有更大的元素,这个表单就派上了用场。文档要:
。。。它是使用obj的大小副本创建的,即对同一obj的大小引用
以及:
。。。返回通过连接self的int副本生成的新数组
因此,在这两种形式中,您都会感到惊讶,最终会得到对同一个x对象的三个引用,正如您所发现的。我想说,您可能会对设计决策提出异议,但这是一种有记录的故意行为,而不是bug
我所知道的在不手动写入数组文本[x,x,x]的情况下获得所需行为的最佳方法是
当然,只要有三个元素,这没什么大不了的,但是如果有更大的元素,这个形式就很方便。简而言之,虽然x只是一个文字,但它是一个对象。您使用[x']*3,因此a包含3个相同的对象。如果将“a”插入其中一个,它们将全部更改 简而言之,虽然x只是一个文字,但它是一个对象。您使用[x']*3,因此a包含3个相同的对象。如果将“a”插入其中一个,它们将全部更改 您可以在上一个示例中省去未使用的块变量。@MichaelKohl谢谢-我真不敢相信这些年来我一直忽略了这个细节!答案现在更新了。@Darshan,我甚至读了文档,有些人怎么没读到。非常感谢。然而,这仍然让我想知道为什么[0]=a+a[0]在我的第一篇文章中初始化时只修改第一个元素……a[0]=a+a[0]没有修改a[0]处的字符串,它创建了一个新字符串a+a[0],并将[0]设置为引用该字符串而不是旧值。[0]用来引用的值未受损坏,[1]和[2]碰巧仍然指向该旧值。这是有道理的。非常感谢。您可以在上一个示例中省去未使用的块变量。@MichaelKohl谢谢-我真不敢相信这些年来我一直忽略了这个细节!答案现在更新了。@Darshan,我甚至读了文档,有些人怎么没读到。非常感谢。然而,这仍然让我想知道为什么[0]=a+a[0]在我的第一篇文章中初始化时只修改第一个元素……a[0]=a+a[0]没有修改a[0]处的字符串,它创建了一个新字符串a+a[0],并将[0]设置为引用该字符串而不是旧值。[0]用来引用的值未受损坏,[1]和[2]碰巧仍然指向该旧值。这是有道理的。非常感谢。相关但不完全相同:相关但不完全相同:
a = Array.new(3) {"x"}