Warum unterstützt Ruby i ++ oder i- (increment / decrement operators) nicht?

Der pre / post-Inkrement / Dekrement-Operator ( ++ und -- ) ist eine ziemlich standardisierte Programmiersprachensyntax (zumindest für prozedurale und objektorientierte Sprachen).

Warum unterstützt Ruby sie nicht? Ich verstehe, dass Sie das Gleiche mit += und -= , aber es scheint seltsamerweise willkürlich, so etwas auszuschließen, zumal es so prägnant und konventionell ist.

Beispiel:

 i = 0 #=> 0 i += 1 #=> 1 i #=> 1 i++ #=> expect 2, but as far as I can tell, #=> irb ignores the second + and waits for a second number to add to i 

Ich verstehe, Fixnum ist unveränderlich, aber wenn += kann einfach ein neues Fixnum und es setzen, warum nicht dasselbe für ++ tun?

Ist die Konsistenz in Zuweisungen, die das Zeichen = , der einzige Grund dafür, oder fehlt mir etwas?

   

Hier erklärt Matz (Yukihiro Matsumoto) es in einem alten Thread :

 Hi, In message "[ruby-talk:02706] X++?" on 00/05/10, Aleksi Niemelä  writes: |I got an idea from http://www.pragprog.com:8080/rubyfaq/rubyfaq-5.html#ss5.3 |and thought to try. I didn't manage to make "auto(in|de)crement" working so |could somebody help here? Does this contain some errors or is the idea |wrong? (1) ++ and -- are NOT reserved operator in Ruby. (2) C's increment/decrement operators are in fact hidden assignment. They affect variables, not objects. You cannot accomplish assignment via method. Ruby uses +=/-= operator instead. (3) self cannot be a target of assignment. In addition, altering the value of integer 1 might cause severe confusion throughout the program. matz. 

Ein Grund ist, dass bisher jeder Zuweisungsoperator (dh ein Operator, der eine Variable ändert) ein = drin hat. Wenn Sie ++ und -- hinzufügen, ist das nicht mehr der Fall.

Ein weiterer Grund ist, dass das Verhalten von ++ und -- oft Leute verwirrt. Fall in Punkt: Der Rückgabewert von i++ in Ihrem Beispiel wäre tatsächlich 1, nicht 2 (der neue Wert von i wäre jedoch 2).

In OO-Sprachen ist es nicht üblich. Tatsächlich gibt es in Smalltalk kein ++ , die Sprache, die den Begriff “objektorientierte Programmierung” geprägt hat (und die Sprache, in der Ruby am stärksten beeinflusst ist). Was du meinst ist, dass es konventionell in C ist und Sprachen, die C fast nachahmen. Ruby hat eine C-ähnliche Syntax, aber es ist nicht sklavisch, wenn man C-Traditionen anpasst.

Warum es nicht in Ruby ist: Matz wollte es nicht. Das ist wirklich der ultimative Grund.

Der Grund, warum so etwas in Smalltalk nicht existiert, ist, dass es Teil der übergeordneten Philosophie der Sprache ist, dass das Zuweisen einer Variable grundsätzlich eine andere Sache ist als das Senden einer Nachricht an ein Objekt – es ist auf einer anderen Ebene. Dieses Denken beeinflusste wahrscheinlich Matz beim Entcasting von Ruby.

Es wäre nicht unmöglich, es in Ruby zu integrieren – Sie könnten leicht einen Präprozessor schreiben, der alle ++ in +=1 umwandelt. aber offensichtlich mochte Matz die Idee eines Operators nicht, der eine “verborgene Aufgabe” machte. Es erscheint auch ein wenig seltsam, einen Operator mit einem versteckten Integer-Operanden darin zu haben. Kein anderer Operator in der Sprache funktioniert so.

Ich denke, es gibt noch einen anderen Grund: ++ in Ruby wäre nicht so nützlich wie in C und seinen direkten Nachfolgern.

Der Grund dafür ist das for Schlüsselwort: Während es in C essentiell ist, ist es in Ruby meistens überflüssig. Der größte Teil der Iteration in Ruby erfolgt über Enumerable-Methoden, z. B. each und map beim Durchlaufen einiger Datenstrukturen, und Fixnum#times Methode, wenn Sie eine exakte Anzahl von Fixnum#times müssen.

Tatsächlich, so weit ich gesehen habe, wird die meiste Zeit +=1 von Leuten benutzt, die von C-artigen Sprachen zu Ruby migriert wurden.

Kurz gesagt, es ist wirklich fraglich, ob die Methoden ++ und -- überhaupt verwendet werden.

Ich denke, Matz ‘Argumentation dafür, dass er sie nicht mag, ist, dass sie die Variable durch eine neue ersetzt.

Ex:

 a = SomeClass.new
 def a.go
   'Hallo'
 Ende
 # An dieser Stelle können Sie a.go anrufen
 # aber wenn du ein a ++ gemacht hast
 # das bedeutet wirklich a = a + 1
 # so können Sie a.go nicht mehr anrufen
 # wie du dein Original verloren hast

Nun, wenn ihn jemand überzeugen könnte, dass er einfach #succ anrufen soll! oder was nicht, das würde mehr Sinn machen und das Problem vermeiden. Sie können es auf Rubykern vorschlagen.

Sie können einen .+ Selbstinkrement-Operator definieren:

 class Variable def initialize value = nil @value = value end attr_accessor :value def method_missing *args, &blk @value.send(*args, &blk) end def to_s @value.to_s end # pre-increment ".+" when x not present def +(x = nil) x ? @value + x : @value += 1 end def -(x = nil) x ? @value - x : @value -= 1 end end i = Variable.new 5 puts i #=> 5 # normal use of + puts i + 4 #=> 9 puts i #=> 5 # incrementing puts i.+ #=> 6 puts i #=> 6 

Weitere Informationen zu “class Variable” finden Sie unter ” Class Variable zum Inkrementieren von Fixnum-Objekten “.

Und in den Worten von David Black aus seinem Buch “The Well-Grounded Rubyist”:

Einige Objekte in Ruby werden in Variablen als unmittelbare Werte gespeichert. Dazu gehören Ganzzahlen, Symbole (die wie folgt aussehen) und die Spezialobjekte wahr, falsch und null. Wenn Sie einen dieser Werte einer Variablen zuweisen (x = 1), enthält die Variable den Wert selbst und keine Referenz darauf. In der Praxis spielt dies keine Rolle (und es wird oft implizit bleiben, anstatt es wiederholt zu formulieren, in Diskussionen über Referenzen und verwandte Themen in diesem Buch). Ruby behandelt die Dereferenzierung von Objektreferenzen automatisch; Sie müssen keine zusätzlichen Aufgaben ausführen, um eine Nachricht an ein Objekt zu senden, das beispielsweise einen Verweis auf eine Zeichenfolge enthält, im Gegensatz zu einem Objekt, das einen unmittelbaren Ganzzahlwert enthält. Die Regel für die unmittelbare Wertdarstellung hat jedoch einige interessante Konsequenzen, insbesondere wenn es sich um Ganzzahlen handelt. Zum einen ist jedes Objekt, das als unmittelbarer Wert dargestellt wird, immer genau dasselbe Objekt, egal wie viele Variablen es zugeordnet ist. Es gibt nur ein Objekt 100, nur ein Objekt ist falsch und so weiter. Die unmittelbare, einzigartige Natur integer-gebundener Variablen liegt hinter dem Fehlen von Vor- und Nach-Inkrement-Operatoren von Ruby – das heißt, Sie können dies in Ruby nicht tun: x = 1 x ++ # Kein solcher Operator Der Grund dafür ist der Grund zu der unmittelbaren Anwesenheit von 1 in x, x ++ wäre wie 1 ++, was bedeutet, dass Sie die Zahl 1 in die Zahl 2 ändern würden – und das macht keinen Sinn.

Könnte dies nicht erreicht werden, indem der class fixnum oder Integer eine neue Methode hinzugefügt wird?

 $ ruby -e 'numb=1;puts numb.next' 

gibt 2 zurück

“Destruktive” Methoden scheinen angefügt zu sein ! um mögliche Benutzer zu warnen, also eine neue Methode namens next! hinzufügen next! würde ziemlich viel tun, was angefordert wurde, dh.

 $ ruby -e 'numb=1; numb.next!; puts numb' 

gibt 2 zurück (seit tumb wurde inkrementiert)

Natürlich, das next! Methode müsste überprüfen, dass das Objekt eine Integer-Variable und keine reelle Zahl war, aber dies sollte verfügbar sein.

Überprüfen Sie diese Operatoren aus der C-Familie in Ruby’s irb und testen Sie sie selbst:

 x = 2 # x is 2 x += 2 # x is 4 x++ # x is now 8 ++x # x reverse to 4