Странное различие между переменной Integer и переменной Array - PullRequest
2 голосов
/ 12 апреля 2011
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] 

но Array

def bla x
 x << 1
end

bla a # => [1,1]

a # =>[1,1] stay in the new value 

Может ли кто-нибудь сказать мне, почему это так?

Ответы [ 4 ]

3 голосов
/ 12 апреля 2011

Существует разница между изменяемым и неизменным объектами.

  • Numerical является неизменным;другими словами, если у вас был объект 1, вы не можете изменить его значение на 2.1 и 2 всегда будут разными объектами, имеющими разные идентификаторы объектов.1+1 возвращает обратно только что созданный 2, который отличается от 1.

  • Array, Hash, Stringизменчивый;другими словами, если у вас был объект [], вы можете изменить его на [1], сохранив его идентичность, и это то, что делает ваш код.Даже если значение теперь другое, это тот же объект, что и [] ранее.

Но в вашем случае вы сравниваете Fixnum#+ и Array#<< и утверждаете, что ониразные.Это не странно.Это разные методы, почему вы ожидаете, что они будут одинаковыми?На самом деле, как указывает мю, если вы сделаете a+[1], это не изменит a.Он делает то, что сравнимо с Fixnum#+: создает новый объект и возвращает его.

На самом деле ваш вопрос должен задаваться так: почему нет аналога Numerical#<<, который ведет себя как Array#<<?Мутабильное и неизменное различие, приведенное выше, является ответом на него.

2 голосов
/ 12 апреля 2011

Эта версия вашего целого числа 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

ближе к вашему целому числу.Этот массив-бла оставит a неизменным.

Ваш массив-бла изменит a, поскольку x << 1 совпадает с x.push(1), а метод push изменяет массив.x, который видит ваш массив, является ссылкой, указывающей на тот же объект, что и a.

2 голосов
/ 12 апреля 2011

Это потому, что вызов метода << отредактирует значение в ссылке на массив.

Если вы не хотите, чтобы это произошло, вы можете сделать:

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] 

Это будет использовать Объект # dup , который будет делать поверхностную копию.

Если вы хотите глубокую копию, вы можете использовать Object # clone .

1 голос
/ 12 апреля 2011

Оператор «<<» всегда добавляет значение к существующей переменной (по ссылке), а другие - нет. </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...