Почему номера не поддерживают .dup? - PullRequest
7 голосов
/ 26 декабря 2009
>> a = 5
=> 5
>> b = "hello, world!"
=> "hello, world!"
>> b.dup
=> "hello, world!"
>> a.dup
TypeError: can't dup Fixnum
    from (irb):4:in `dup'
    from (irb):4

Я понимаю, что Ruby будет делать копию каждый раз, когда вы назначаете целое число новой переменной, но почему Numeric#dup вызывает ошибку?

Не нарушит ли это абстракцию, поскольку все объекты должны правильно реагировать на .dup?

Переписывание метода dup решит проблему, насколько я могу судить:

>> class Numeric
>>   def dup()
>>     self
>>   end
>> end

Есть ли у этого недостаток, которого я не вижу? Почему это не встроено в Ruby?

Ответы [ 2 ]

15 голосов
/ 26 декабря 2009

Большинство объектов в Ruby передаются по ссылке и могут быть сброшены. Например:

s = "Hello"
t = s      # s & t reference to the same string
t.upcase!  # modifying either one will affect the other
s # ==> "HELLO"

Однако несколько объектов в Ruby являются непосредственными. Они передаются по значению, может быть только одно из этого значения и поэтому не может быть дублировано. Это любые (маленькие) целые числа, true, false, символы и nil. Многие типы с плавающей точкой также доступны в Ruby 2.0 в 64-битных системах.

В этом (нелепом) примере любой «42» будет содержать одну и ту же переменную экземпляра.

class Fixnum
  attr_accessor :name
  alias_method :original_to_s, :to_s
  def to_s
    name || original_to_s
  end
end
42.name = "The Answer"
puts *41..43  # =>  41, The Answer, 43

Поскольку вы, как правило, ожидаете, что something.dup.name = "new name" не повлияет ни на какой другой объект, кроме копии, полученной с помощью dup, Ruby решает не определять dup сразу.

Ваш вопрос сложнее, чем кажется. Было некоторое обсуждение о том, как это можно сделать проще. Кроме того, другие типы числовых объектов (числа с плавающей запятой, числовые значения, рациональные и комплексные числа) не могут быть дублированы, хотя они также не являются непосредственными.

Обратите внимание, что ActiveSupport (часть рельсов) предоставляет метод duplicable? для всех объектов

3 голосов
/ 26 декабря 2009

Проблема с определенной вами функцией dup() заключается в том, что она не возвращает копию объекта, а возвращает сам объект. Это не то, что должна делать duplicate процедура.

Я не знаю Ruby, но возможная причина, по которой я могу подумать, что dup не определена для чисел, состоит в том, что число является базовым типом и, следовательно, делает что-то вроде:

>> a = 5
>> b = a

автоматически присвоит значение 5 переменной b, в отличие от b и a, указывающих на одно и то же значение в памяти.

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