2014-01-07 10 views
7

Ich konnte nicht verstehen, warum in Ruby, Array#slice und Array#slice! verhalten sich anders als Array#sort und Array#sort! (in der Art, wie man die Ergebnisse auf einem neuen Array und die andere auf das aktuelle Objekt zurückgibt).Warum Array # Slice und Array # Slice! sich anders verhalten?

Mit sort gibt die erste (ohne Knall) eine sortierte Kopie des aktuellen Arrays zurück, und sort! sortiert das aktuelle Array.

slice, gibt einen Array mit dem angegebenen Bereich, und slice!löscht den spezifizierten Bereich von dem aktuellen Objekt.

Was ist der Grund dafür, dass sich Array#slice! so verhält, anstatt das aktuelle Objekt zu einem Array mit dem angegebenen Bereich zu machen?

Beispiel:

a = [0,1,2,3,4,5,6,7,8,9] 

b = a.slice(2,2) 

puts "slice:" 
puts " a = " + a.inspect 
puts " b = " + b.inspect 

b = a.slice!(2,2) 
puts "slice!:" 
puts " a = " + a.inspect 
puts " b = " + b.inspect 

Output:

slice: 
    a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
    b = [2, 3] 
slice!: 
    a = [0, 1, 4, 5, 6, 7, 8, 9] 
    b = [2, 3] 

http://ideone.com/77xFva

+2

Mit '!'auf einer Methode hat kein gesetztes Verhalten, es ist nur da, um anzuzeigen, dass die Methode in irgendeiner Weise die Eingabe verändert, während sie auch die exakt gleiche Ausgabe hat. Sie können es am Ende jeder von Ihnen geschriebenen Methode hinzufügen. – tpbowden

Antwort

3

#slice und #slice! Verhalten äquivalent sind: beide „Rückkehr ein Subarray am Start Index begonnen und für Länge Elemente fort“, auf die gleiche Weise wie #sort und #sort! ein sortiertes Array oder #reverse zurückzukehren und #reverse! Rück eine umgekehrte Array.

Der Unterschied ist, dass die Bang-Methoden auch das Objekt selbst modifizieren.

a = [4,2,6,9,1,5,8] 
b = a.dup 
a.sort == b.sort!    # => true 
a == b      # => false 

b = a.dup 
a.reverse == b.reverse!  # => true 
a == b      # => false 

b = a.dup 
a.slice(2,2) == b.slice!(2,2) # => true 
a == b      # => false 
+0

Das hat der Benutzer nicht gefragt. Er weiß davon, er fragt nach einer Designentscheidung. Insbesondere warum Slice! ersetzt das aktuelle Objekt nicht durch das Ergebnis. –

+2

'# slice' (und' #slice! ') _" Gibt nil zurück, wenn der Index außerhalb des gültigen Bereichs liegt "_. Diese Situation ist unvereinbar mit der Idee, das Objekt durch den zurückgegebenen Wert – wacko

+0

zu ersetzen, was wahrscheinlich eine der besten Erklärungen ist, die ich bisher gelesen habe. +1 –

1

! oder Bang Methoden in rubin typischerweise mutieren das vorhandene Objekt gegenüber dem nicht-Bang-Verfahren äquivalent, die ein neues kehrt Objekt. Wenn Sie das vorhandene Objekt ändern möchten, verwenden Sie die Option bang method.

EDIT: die Design-Entscheidung zu adressieren, ich bin nicht Matz, aber ich werde erraten, dass, weil die Art der slice eine Teilmenge zurückzukehren, ist es die Teilmenge liefert in jedem Fall. Für andere Knallmethoden wie gsub oder sort modifizieren Sie (möglicherweise) die gesamte Zeichenfolge/das gesamte Objekt, so dass entweder eine Kopie zurückgegeben wird oder das Original mit den Änderungen zurückgegeben wird.

+1

Das hat der Benutzer nicht gefragt. Er weiß davon, er fragt nach einer Designentscheidung. Insbesondere warum Slice! ersetzt das aktuelle Objekt nicht durch das Ergebnis. –

+0

@SimoneCarletti vielleicht hilft das? –

0

Ich denke, die Idee hinter der Design-Entscheidung ist, dass, wenn Sie Array#slice! rufen dann bereits Sie einen Zeiger auf die Scheibe des Arrays haben (vorausgesetzt, Sie es zu einer Variablen zugewiesen). Die logische Entscheidung besteht darin, das Objekt so zu modifizieren, dass sich die Scheibe nicht mehr im ursprünglichen Array befindet.

Sie können sehen, wie dies zum Beispiel in einer Schleife nützlich wäre. Wenn du ein Stück der ersten drei Elemente des Arrays nehmen willst, dann tu etwas mit diesen drei Elementen und höre auf, wenn es nicht mehr gibt, du könntest Array#slice! verwenden und es würde schließlich das Array zerstören.

Nun, wenn Sie sich vorstellen, dass das Array aus dem Beispiel eine Warteschlange oder ein Stapel war, würde es Sinn machen, warum Sie Teile des Arrays entfernen möchten.