>> 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?
Большинство объектов в Рубине передаются по ссылке и могут быть отброшены. Eg:
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
. На 64-битных системах многие флоты также являются непосредственными в Ruby 2.0.
В этом (нелепым) примере любая "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 = "новое имя"
не повлияет ни на какой другой объект, кроме копии, полученной с помощью dup
, Ruby решает не определять dup
на непосредственных числах.
Ваш вопрос сложнее, чем кажется на первый взгляд. Было некоторое обсуждение по поводу рубинового ядра о том, как это можно сделать проще. Также, другие типы числовых объектов (плавающие, бинумы, нормированные и комплексные числа) нельзя дублировать, хотя они и не являются мгновенными.
Обратите внимание, что ActiveSupport (часть рельсов) предоставляет метод дублируемый?
на всех объектах
Проблема с функцией dup()
, которую вы определили, заключается в том, что она не возвращает копию объекта, а возвращает сам объект. Это не то, что должна делать процедура dup()
.
Я не знаю Руби, но возможная причина, по которой dup
не определено для чисел, заключается в том, что число является базовым типом и, таким образом, делая что-то вроде:
>> a = 5
>> b = a
автоматически присваивает значение 5
переменной b
, в отличие от того, чтобы b
и a
указывали на одно и то же значение в памяти.