2009-12-26 10 views
7

Ich verstehe, dass Ruby jedes Mal eine Kopie erstellt, wenn Sie einer neuen Variablen eine ganze Zahl zuweisen, aber warum gibt Numeric#dup einen Fehler?Warum unterstützen keine Nummern .dup?

Würde dies nicht die Abstraktion unterbrechen, da erwartet werden sollte, dass alle Objekte korrekt auf .dup reagieren?

Umschreiben der dup Methode das Problem beheben, soweit ich sagen kann:

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

Hat dies einen Nachteil ich sehe nicht? Warum ist das nicht in Ruby integriert?

Antwort

14

Die meisten Objekte in Ruby werden als Referenz übergeben und können dupliziert werden. ZB:

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

Einige Objekte in Ruby sind jedoch sofort. Sie werden nach Wert übergeben, es kann nur einen Wert geben, der nicht getäuscht werden kann. Dies sind beliebige (kleine) Ganzzahlen, true, false, Symbole und nil. Viele Floats sind auch direkt in Ruby 2.0 auf 64-Bit-Systemen.

In diesem (absurden) Beispiel enthält jedes "42" dieselbe Instanzvariable.

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 

Da Sie normalerweise erwarten würden something.dup.name = "new name" kein anderes Objekt beeinflussen als die Kopie mit dup erhalten, wählt Rubin nicht dup auf immediates zu definieren.

Ihre Frage ist komplexer als es scheint. Es gab some discussion auf Rubin-Kern, wie dies erleichtert werden kann. Auch andere Arten von numerischen Objekten (Floats, Bignums, Rationales und komplexe Zahlen) können nicht getäuscht werden, obwohl sie auch nicht unmittelbar sind.

Beachten Sie, dass Active (Teil der Schienen) duplicable? für alle Objekte die Methode bietet

+1

ActiveSupport, nicht Rails, bietet die 'duplizierbare?' Methode.Sie könnten also ActiveSupport installieren und benötigen ('require 'active_support'), wenn Sie diese (und viele andere) Hilfsmethoden möchten. – henrikhodne

+0

In der Tat. Aktualisiert. –

+0

Der Link sollte durch https://bugs.ruby-lang.org/issues/1844 ersetzt werden. Außerdem wurde das Feature abgelehnt, da offensichtlich keine Fortschritte erzielt wurden. –

2

Das Problem mit der von Ihnen definierten dup()-Funktion ist, dass es keine Kopie des Objekts zurückgibt, sondern das Objekt selbst zurückgibt. Dies ist nicht, was eine duplicate Prozedur tun soll.

Ich weiß nicht, Rubin, aber ein möglicher Grund, warum ich denken kann, für dup nicht für Zahlen definiert ist, ist, dass eine Reihe ein Grundtyp ist und somit, wie etwas zu tun:

>> a = 5 
>> b = a 

würde automatisch Weisen Sie den Wert 5 der Variablen b zu, anstatt b und a auf denselben Wert im Speicher zu zeigen.

+0

Das ist genau das, was Rubin tut, so, wenn Sie meine Methode mit einem numerischen Typ verwenden, wird es eine neue Kopie zurück. (und für jeden anderen Typ, wird es einen Verweis auf das Original zurückgeben) –

+0

Ich nehme an, das ist wahr. Aus funktionaler Sicht gibt es wahrscheinlich kein Problem mit Ihrem Code. Der Grund, warum Ruby es nicht eingebaut hat, ist höchstwahrscheinlich, weil es nur die eingebaute Zuweisungsfunktionalität von Rubys Grundtypen dupliziert. – cmptrgeekken

Verwandte Themen