【问题标题】:Why don't numbers support .dup?为什么数字不支持.dup?
【发布时间】:2010-12-30 03:58:57
【问题描述】:
>> 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 内置的?

【问题讨论】:

    标签: ruby numbers abstraction


    【解决方案1】:

    Ruby 中的大多数对象都是通过引用传递的,并且可以复制。例如:

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

    不过,Ruby 中的一些对象是直接的。它们是按值传递的,这个值只能有一个,因此不能被欺骗。这些是任何(小)整数,truefalse、符号和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 = "new name" 不会影响除使用dup 获得的副本之外的任何其他对象,因此Ruby 选择不在立即数上定义dup

    您的问题比看起来更复杂。 ruby-core 上有some discussion 说明如何使这变得更容易。此外,其他类型的 Numeric 对象(浮点数、大数、有理数和复数)也不能被欺骗,尽管它们也不是立即数。

    注意 ActiveSupport(rails 的一部分)在所有对象上都提供了 duplicable? 方法

    【讨论】:

    • ActiveSupport,而不是 Rails,提供了duplicable? 方法。因此,如果您需要该(以及许多其他)实用程序方法,您可以安装 ActiveSupport 并要求它 (require 'active_support')。
    • 链接应替换为bugs.ruby-lang.org/issues/1844。此外,该功能被拒绝,因为显然没有取得任何进展。
    【解决方案2】:

    您定义的dup() 函数的问题在于它不返回对象的副本,而是返回对象本身。这不是duplicate 过程应该做的事情。

    我不了解 Ruby,但我能想到 dup 未定义为数字的一个可能原因是数字是基本类型,因此,可以执行以下操作:

    >> a = 5
    >> b = a
    

    会自动将值5 分配给变量b,而不是让ba 指向内存中的相同值。

    【讨论】:

    • 这正是 Ruby 所做的,因此当您将我的方法用于数字类型时,它将返回一个新副本。 (对于任何其他类型,它将返回对原始的引用)
    • 我想这是真的。那么,从功能的角度来看,您的代码可能没有问题。然而,Ruby 没有内置它的原因很可能是因为它只是复制了 Ruby 基本类型的内置赋值功能。
    猜你喜欢
    • 2021-12-12
    • 2018-04-02
    • 1970-01-01
    • 2013-08-11
    • 2011-03-17
    • 2018-07-21
    • 2013-01-04
    • 2017-10-07
    • 2018-08-24
    相关资源
    最近更新 更多