a = 1
def bla x
x = x + 1
end
bla a # =>2 when I use bla to add 1, it return 2
a # => 1 but it get back to the original value
a = [1]
但是数组
def bla x
x << 1
end
bla a # => [1,1]
a # =>[1,1] stay in the new value
有人可以告诉我它为什么会这样吗?
答案 0 :(得分:3)
可变和不可变对象之间存在差异。
Numerical
是不可变的;换句话说,如果您拥有对象1
,则无法将其值更改为2
。 1
和2
将始终是不同的对象,具有不同的对象ID。 1+1
正在做的是返回新创建的2
,这是与1
不同的对象。
Array
,Hash
,String
是可变的;换句话说,如果您拥有对象[]
,则可以将其更改为[1]
保留其标识,这就是您的代码所做的事情。即使该值现在不同,它与[]
之前的对象相同。
但在您的情况下,您正在比较Fixnum#+
和Array#<<
并声称它们不同。这并不奇怪。它们是不同的方法,为什么你们期望它们是相同的?事实上,正如mu指出的那样,如果你做a+[1]
,那就不会改变a
。它具有与Fixnum#+
相当的效果:创建一个新对象并将其返回。
您的问题应该是真正的问题:为什么没有对应Numerical#<<
的行为类似于Array#<<
?上面的可变与不可变的差异就是答案。
答案 1 :(得分:2)
这是因为调用<<
方法将编辑数组引用的值。
如果您不希望这种情况发生,您可以这样做:
def bla x
x + [1]
end
这可以通过将数组x
与数组[1]连接起来,从此操作返回一个新数组。
或:
ruby-1.9.2-p136 :007 > bla a.dup
=> [1, 1]
ruby-1.9.2-p136 :008 > a
=> [1]
这将使用Object#dup,它将执行浅拷贝。
如果您需要深层副本,可以使用Object#clone。
答案 2 :(得分:2)
此整数版本bla
:
def bla x
x += 1
end
a = 1
bla a
更靠近你的阵列。但是,即使这个也不会改变a
,因为Fixnum
实例是不可变的;如果Fixnum
个实例不是不可变的,那么你就会让人们改变1的值,而这只会造成很大的混乱。
此版本的数组bla
:
def bla x
x + [1]
end
a = [1]
bla a
更接近你的整数1。这个array-bla将a
保持不变。
您的阵列更改a
,因为x << 1
与x.push(1)
相同,而push
方法会修改数组。您的array-bla看到的x
是指向a
所指向的同一对象的引用。
答案 3 :(得分:1)
'&LT;&LT;'运算符总是将值附加到现有变量(通过引用),但其他变量不会。