Der Pre / Post-Inkrement / Dekrement-Operator ( ++
und --
) ist eine ziemlich standardmäßige Programmiersprachen-Syntax (zumindest für prozedurale und objektorientierte Sprachen).
Warum unterstützt Ruby sie nicht? Ich verstehe, dass Sie mit +=
und dasselbe erreichen können -=
, 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 +=
man nur ein neues instanziieren Fixnum
und einstellen kann, warum nicht das Gleiche für ++
?
Ist die Konsistenz bei Aufgaben, die den =
Charakter enthalten, der einzige Grund dafür, oder fehlt mir etwas?
ruby
operators
language-design
Andy_Vulhop
quelle
quelle
+=
Operator keine Vorinkrementierung durchführen . Versuchen Sie in CI,++
/--
nur innerhalb von Bedingungen zu verwenden, und bevorzugen Sie das wörtlichere+=
/-=
in einer grundlegenden Anweisung. Wahrscheinlich, weil ich Python gelernt habe (allerdings lange nach C ...)Antworten:
So erklärt es Matz (Yukihiro Matsumoto) in einem alten Thread :
quelle
+=
/-=
ok? Und wäre das nicht1+=1
genauso schlimm? (Es schlägt im IRB mit fehlsyntax error, unexpected ASSIGNMENT
)+=
Ersetzt das Objekt, auf das die Variable verweist, durch ein ganz neues Objekt. Sie können dies überprüfen, indem Siei.object_id
vorher und nachher anrufeni+=1
. Warum sollte das technisch schwieriger sein++
?++
Methode zu erstellen ).Ein Grund ist, dass bisher jeder Zuweisungsoperator (dh ein Operator, der eine Variable ändert) einen enthält
=
. Wenn Sie++
und hinzufügen--
, ist dies nicht mehr der Fall.Ein weiterer Grund ist, dass das Verhalten von Menschen
++
und--
oft verwirrt.i++
Beispiel : Der Rückgabewert von in Ihrem Beispiel wäre tatsächlich 1, nicht 2 (der neue Wert voni
wäre jedoch 2).quelle
=
scheint die Begründung, dass "alle Aufgaben einen in sich haben", sinnvoll zu sein. Ich kann das als ein starkes Festhalten an der Konsistenz respektieren.a.capitalize!
wird nicht neu zugewiesena
, sondern die Zeichenfolge,a
auf die verwiesen wird , wird mutiert . Andere Verweise auf dieselbe Zeichenfolge sind betroffen. Wenn Sie diesa.object_id
vor und nach dem Aufruf von tuncapitalize
, erhalten Sie dasselbe Ergebnis (beides wäre nicht der Fall, wenn Sie diesa = a.capitalize
stattdessen tun würden ).a.capitalize!
sich auf andere Verweise auf dieselbe Zeichenfolge aus. Das ist ein praktischer Unterschied. Zum Beispiel, wenn Sie habendef yell_at(name) name.capitalize!; puts "HEY, #{name}!" end
und Sie es dann so nennen :my_name = "luis"; yell_at(my_name)
, wird der Wert vonmy_name
jetzt sein"LUIS"
, während es nicht beeinflusst würde, wenn Siecapitalize
und eine Zuordnung verwendet hätten.Es ist nicht konventionell in OO-Sprachen. Tatsächlich gibt es
++
in Smalltalk keine Sprache, die den Begriff "objektorientierte Programmierung" geprägt hat (und die Sprache, von der Ruby am stärksten beeinflusst wird). Was Sie damit meinen, ist, dass es in C konventionell ist und Sprachen C stark imitieren. Ruby hat eine etwas C-ähnliche Syntax, aber es ist nicht sklavisch, wenn man sich an C-Traditionen hält.Warum es nicht in Ruby ist: Matz wollte es nicht. Das ist wirklich der ultimative Grund.
Der Grund , so etwas in Smalltalk vorhanden ist , weil es Teil der Sprache der Philosophie überschreibt , dass ein variable Zuordnung ist im Grunde eine andere Art von Sache , als eine Nachricht an ein Objekt zu senden - es auf einer anderen Ebene ist. Dieses Denken hat Matz wahrscheinlich bei der Gestaltung von Ruby beeinflusst.
Es wäre nicht unmöglich, es in Ruby aufzunehmen - Sie könnten leicht einen Präprozessor schreiben, der alles
++
in verwandelt+=1
. aber offensichtlich mochte Matz die Idee eines Operators, der eine "versteckte Aufgabe" ausführte, nicht. Es scheint auch ein wenig seltsam, einen Operator mit einem versteckten ganzzahligen Operanden darin zu haben. Kein anderer Operator in der Sprache funktioniert so.quelle
Ich denke, es gibt noch einen anderen Grund:
++
In Ruby wäre es nicht im entferntesten nützlich wie in C und seinen direkten Nachfolgern.Der Grund dafür ist das
for
Schlüsselwort: Während es in C wichtig ist, ist es in Ruby meistens überflüssig. Der größte Teil der Iteration in Ruby erfolgt mit Enumerable-Methoden, z. B.each
undmap
beim Durchlaufen einer Datenstruktur und einerFixnum#times
Methode, wenn Sie eine genaue Anzahl von Schleifen durchführen müssen.Soweit ich gesehen habe, wird die meiste Zeit
+=1
von Leuten verwendet, die frisch aus C-Sprachen nach Ruby migriert sind.Kurz gesagt, es ist wirklich fraglich, ob Methoden
++
und--
überhaupt verwendet werden würden.quelle
Ich denke, Matz argumentiert, dass er die Variable tatsächlich durch eine neue ersetzt.
Ex:
Wenn ihn jemand davon überzeugen könnte, dass er einfach #succ anrufen sollte! oder was nicht, das wäre sinnvoller und würde das Problem vermeiden. Sie können es auf Rubinkern vorschlagen.
quelle
Sie können einen
.+
Selbstinkrementierungsoperator definieren :Weitere Informationen zu "Klassenvariable" finden Sie unter " Klassenvariable zum Inkrementieren von Fixnum-Objekten ".
quelle
Und in den Worten von David Black aus seinem Buch "The Well-Grounded Rubyist":
quelle
Könnte dies nicht erreicht werden, indem der Klasse fixnum oder Integer eine neue Methode hinzugefügt wird?
gibt 2 zurück
"Destruktive" Methoden scheinen angehängt zu sein
!
, um mögliche Benutzer zu warnen. Das Hinzufügen einer neuen Methode namensnext!
würde also so ziemlich das tun, was angefordert wurde, d. H.gibt 2 zurück (da numb erhöht wurde)
Natürlich
next!
müsste die Methode überprüfen, ob das Objekt eine ganzzahlige Variable und keine reelle Zahl ist, aber dies sollte verfügbar sein.quelle
Integer#next
existiert bereits (mehr oder weniger), außer es wirdInteger#succ
stattdessen aufgerufen (für 'Nachfolger'). AberInteger#next!
(oderInteger#succ!
) wäre Unsinn: Denken Sie daran, dass Methoden an Objekten arbeiten , nicht an Variablen . Sienumb.next!
wären also genau gleich1.next!
, dh sie würden 1 mutieren, um gleich 2 zu sein .++
wäre etwas besser, da es syntaktischer Zucker für eine Aufgabe sein könnte, aber ich persönlich bevorzuge die aktuelle Syntax, bei der alle Aufgaben erledigt sind=
.Integer#pred
um den Vorgänger abzurufen.Überprüfen Sie diese Operatoren aus der C-Familie in Ruby's irb und testen Sie sie selbst:
quelle
(x++)
wie eine ungültige Aussage in Ruby.