L'opérateur d'incrémentation / décrémentation pré / post ( ++
et --
) est une syntaxe de langage de programmation assez standard (au moins pour les langages procéduraux et orientés objet).
Pourquoi Ruby ne les prend-il pas en charge? Je comprends que vous pourriez accomplir la même chose avec +=
et -=
, mais il semble tout simplement bizarrement arbitraire d'exclure quelque chose comme ça, d'autant plus que c'est tellement concis et conventionnel.
Exemple:
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
Je comprends que Fixnum
c'est immuable, mais si vous +=
pouvez simplement instancier un nouveau Fixnum
et le définir, pourquoi ne pas faire de même pour ++
?
La cohérence des affectations contenant le =
personnage est-elle la seule raison à cela, ou est-ce que je manque quelque chose?
ruby
operators
language-design
Andy_Vulhop
la source
la source
+=
opérateur. Dans CI, essayez d'utiliser++
/--
uniquement à l'intérieur des conditions, préférant le plus littéral+=
/-=
dans une instruction de base. Probablement parce que j'ai appris Python (bien après C cependant ...)Réponses:
Voici comment Matz (Yukihiro Matsumoto) l'explique dans un vieux fil :
la source
+=
/-=
ok? Et ne serait pas1+=1
aussi mauvais? (Il échoue dans IRB avecsyntax error, unexpected ASSIGNMENT
)+=
remplace l'objet auquel la variable fait référence par un tout nouvel objet. Vous pouvez vérifier cela en appelanti.object_id
avant et aprèsi+=1
. Pourquoi est-ce que cela serait techniquement plus difficile à faire++
?++
méthode).Une des raisons est que jusqu'à présent, chaque opérateur d'affectation (c'est-à-dire un opérateur qui change une variable) a un
=
en lui. Si vous ajoutez++
et--
, ce n'est plus le cas.Une autre raison est que le comportement
++
et--
souvent confondent les gens.i++
Exemple concret: la valeur de retour de dans votre exemple serait en fait 1, et non 2 (la nouvelle valeur dei
serait cependant 2).la source
=
en eux» semble avoir un sens. Je peux en quelque sorte respecter cela comme une adhésion farouche à la cohérence.a.capitalize!
ne réassigne pasa
, il mute la chaîne quia
fait référence. Les autres références à la même chaîne seront affectées et si vous le faitesa.object_id
avant et après l'appel àcapitalize
, vous obtiendrez le même résultat (qui ne serait pas vrai si vous le faisiez à laa = a.capitalize
place).a.capitalize!
affectera d'autres références à la même chaîne. C'est vraiment une différence pratique. Par exemple, si vous avezdef yell_at(name) name.capitalize!; puts "HEY, #{name}!" end
et que vous l'appelez comme ceci:,my_name = "luis"; yell_at(my_name)
la valeur demy_name
sera maintenant"LUIS"
, alors qu'elle ne serait pas affectée si vous aviez utilisécapitalize
et une affectation.Ce n'est pas conventionnel dans les langages OO. En fait, il n'y
++
en a pas dans Smalltalk, le langage qui a inventé le terme «programmation orientée objet» (et le langage par lequel Ruby est le plus fortement influencé). Ce que vous voulez dire, c'est qu'il est conventionnel en C et que les langages imitant de près C. Ruby a une syntaxe un peu semblable au C, mais ce n'est pas servile à adhérer aux traditions C.Quant à savoir pourquoi ce n'est pas dans Ruby: Matz n'en voulait pas. C'est vraiment la raison ultime.
La raison pour laquelle une telle chose n'existe pas dans Smalltalk est que cela fait partie de la philosophie primordiale du langage selon laquelle l'attribution d'une variable est fondamentalement un autre type de chose que l'envoi d'un message à un objet - c'est à un niveau différent. Cette réflexion a probablement influencé Matz dans la conception de Ruby.
Il ne serait pas impossible de l'inclure dans Ruby - vous pourriez facilement écrire un préprocesseur qui transforme tout
++
en+=1
. mais évidemment, Matz n'aimait pas l'idée d'un opérateur qui faisait une "mission cachée". Il semble également un peu étrange d'avoir un opérateur avec un opérande entier caché à l'intérieur. Aucun autre opérateur dans la langue ne fonctionne de cette façon.la source
Je pense qu'il y a une autre raison:
++
dans Ruby ne serait pas utile à distance comme dans C et ses successeurs directs.La raison en est, le
for
mot - clé: s'il est essentiel en C, il est surtout superflu en Ruby. La plupart de l'itération dans Ruby est effectuée via des méthodes Enumerable, telles queeach
etmap
lors de l'itération dans une structure de données et uneFixnum#times
méthode, lorsque vous devez effectuer une boucle un nombre exact de fois.En fait, pour autant que je l'ai vu, la plupart du temps
+=1
est utilisé par des personnes fraîchement migrées vers Ruby à partir de langages de style C.En bref, on peut vraiment se demander si des méthodes
++
et--
seraient utilisées du tout.la source
Je pense que le raisonnement de Matz pour ne pas les aimer est qu'il remplace en fait la variable par une nouvelle.
ex:
Maintenant, si quelqu'un pouvait le convaincre qu'il devrait simplement appeler #succ! ou quoi pas, cela aurait plus de sens et éviterait le problème. Vous pouvez le suggérer sur un noyau rubis.
la source
Vous pouvez définir un
.+
opérateur d'auto-incrémentation:Plus d'informations sur la "variable de classe" sont disponibles dans " Variable de classe pour incrémenter les objets Fixnum ".
la source
Et comme l'a dit David Black dans son livre "The Well-Grounded Rubyist":
la source
Cela ne pourrait-il pas être réalisé en ajoutant une nouvelle méthode à la classe fixnum ou Integer?
renvoie 2
Les méthodes "destructives" semblent être ajoutées
!
pour avertir les utilisateurs potentiels, donc l'ajout d'une nouvelle méthode appeléenext!
ferait à peu près ce qui a été demandé.renvoie 2 (puisque numb a été incrémenté)
Bien sûr, la
next!
méthode devrait vérifier que l'objet était une variable entière et non un nombre réel, mais cela devrait être disponible.la source
Integer#next
existe déjà (plus ou moins), sauf qu'il est appelé à laInteger#succ
place (pour 'successeur'). MaisInteger#next!
(ouInteger#succ!
) serait absurde: rappelez-vous que les méthodes fonctionnent sur des objets , pas sur des variables , doncnumb.next!
serait exactement égale à1.next!
, c'est-à-dire qu'elle muterait 1 pour être égal à 2 .++
serait légèrement mieux car cela pourrait être du sucre syntaxique pour une affectation, mais personnellement, je préfère la syntaxe actuelle où toutes les affectations sont terminées=
.Integer#pred
pour récupérer le prédécesseur.Vérifiez ces opérateurs de la famille C dans irb de Ruby et testez-les par vous-même:
la source
(x++)
une déclaration invalide dans Ruby.