简体   繁体   English

为什么数字不支持.dup?

[英]Why don't numbers support .dup?

>> 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

I understand that Ruby will make a copy every time you assign an integer to a new variable, but why does Numeric#dup raise an error? 我知道Ruby每次为新变量赋值时都会复制,但为什么Numeric#dup引发错误?

Wouldn't this break abstraction, since all objects should be expected to respond to .dup properly? 这不会破坏抽象,因为所有对象都应该被正确地响应.dup吗?

Rewriting the dup method will fix the problem, as far as I can tell: 重写dup方法将解决问题,据我所知:

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

Does this have a downside I'm not seeing? 这有没有我看不到的缺点? Why isn't this built into Ruby? 为什么不将它内置到Ruby中?

Most objects in Ruby are passed by reference and can be dupped. Ruby中的大多数对象都是通过引用传递的,可以复制。 Eg: 例如:

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

A few objects in Ruby are immediate, though. 但Ruby中的一些对象是直接的。 They are passed by value, there can only be one of this value and it therefore cannot be duped. 它们按值传递,只能有一个这个值,因此不能被欺骗。 These are any (small) integers, true , false , symbols and nil . 这些是任何(小)整数, truefalse ,符号和nil Many floats are also immediates in Ruby 2.0 on 64 bit systems. 在64位系统上的Ruby 2.0中,许多浮点数也是最重要的。

In this (preposterous) example, any "42" will hold the same instance variable. 在这个(荒谬的)示例中,任何“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

Since you would normally expect something.dup.name = "new name" to not affect any other object than the copy obtained with dup , Ruby chooses not to define dup on immediates. 由于您通常期望something.dup.name = "new name"不会影响使用dup获得的副本之外的任何其他对象,因此Ruby选择不在immediates上定义dup

Your question is more complex than it appears. 你的问题比它看起来更复杂。 There was some discussion on ruby-core as to how this can be made easier. 关于如何使这更容易, 讨论了ruby-core。 Also, other types of Numeric objects (floats, bignums, rationals and complex numbers) can not be duped although they are not immediates either. 此外,其他类型的数字对象(浮点数,bignums,有理数和复数)也不能被欺骗,尽管它们也不是中立的。

Note that ActiveSupport (part of rails) provide the method duplicable? 请注意,ActiveSupport(rails的一部分)提供了可重复的方法duplicable? on all objects 在所有对象上

The problem with the dup() function that you defined is that it doesn't return a copy of the object, but rather returns the object itself. 您定义的dup()函数的问题是它不返回对象的副本 ,而是返回对象本身。 This is not what a duplicate procedure is supposed to do. 这不是duplicate程序应该做的事情。

I don't know Ruby, but a possible reason I can think of for dup not being defined for numbers is that a number is a basic type and thus, doing something like: 我不知道Ruby,但是我可以想到没有为数字定义dup一个可能原因是数字是一个基本类型,因此,做类似的事情:

>> a = 5
>> b = a

would automatically assign the value 5 into the variable b , as opposed to making b and a point to the same value in memory. 会自动将值5分配给变量b ,而不是将ba指向内存中的相同值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM