Pourquoi les raccourcis comme x + = y sont-ils considérés comme de bonnes pratiques?

305

Je ne sais pas comment on les appelle, mais je les vois tout le temps. L'implémentation Python est quelque chose comme:

x += 5comme notation abrégée pour x = x + 5.

Mais pourquoi est-ce considéré comme une bonne pratique? Je l'ai retrouvé dans presque tous les livres ou tutoriels de programmation que j'ai lus pour Python, C, R, etc. Je comprends que c'est pratique, en économisant trois frappes, espaces compris. Mais ils semblent toujours me faire trébucher quand je lis du code, et du moins le rendre moins lisible, pas plus.

Me manque-t-il une raison claire et évidente pour laquelle ils sont utilisés partout?

Fomite
la source
@EricLippert: C # gère-t-il cela de la même manière que la réponse principale décrite? Est - il réellement plus efficace sage CLR dire x += 5que x = x + 5? Ou est-ce vraiment juste du sucre syntaxique comme vous le suggérez?
Blesh
24
@blesh: Cela aurait pu être le cas en 1970 si de petits détails sur la manière dont on exprime une addition dans le code source ont une incidence sur l' efficacité du code exécutable résultant. ce n'est certainement pas maintenant. Optimiser les compilateurs est une bonne chose et vous avez plus de soucis qu'une nanoseconde ici ou là. L'idée que l'opérateur + = ait été développé "il y a vingt ans" est évidemment fausse; le regretté Dennis Richie a développé le C de 1969 à 1973 chez Bell Labs.
Eric Lippert
1
Voir blogs.msdn.com/b/ericlippert/archive/2011/03/29/… (voir aussi deuxième partie)
Samedi
5
La plupart des programmeurs fonctionnels considéreront cette mauvaise pratique.
Pete Kirkham

Réponses:

598

Ce n'est pas un raccourci.

Le +=symbole est apparu dans le langage C dans les années 1970 et - avec l’idée C d’assembleur intelligent, correspond à une instruction machine et à un mode d’adressage nettement différents:

Des choses comme " i=i+1", "i+=1"et" ++i", bien qu’à un niveau abstrait produisent le même effet, correspondent à un niveau bas à une manière différente de travailler du processeur.

En particulier ces trois expressions, en supposant que la ivariable réside dans l'adresse de la mémoire stockée dans un registre de la CPU (appelons-la D- pensez à un "pointeur sur int") et que l' ALU du processeur prend un paramètre et renvoie le résultat sous forme de "accumulateur" (appelons-le A - pensez-y comme un int).

Avec ces contraintes (très courantes dans tous les microprocesseurs de cette période), la traduction sera probablement

;i = i+1;
MOV A,(D); //Move in A the content of the memory whose address is in D
ADD A, 1;  //The addition of an inlined constant
MOV (D) A; //Move the result back to i (this is the '=' of the expression)

;i+=1;
ADD (D),1; //Add an inlined constant to a memory address stored value

;++i;
INC (D); //Just "tick" a memory located counter

La première façon de procéder est non optimale, mais elle est plus générale lorsque vous utilisez des variables au lieu de constantes ( ADD A, Bou ADD A, (D+x)) ou lorsque vous traduisez des expressions plus complexes (elles se résument toutes en une opération push de priorité basse dans une pile, appelez la priorité élevée, pop et répétez jusqu'à ce que tous les arguments aient été éliminés).

La seconde est plus typique de "machine à états": nous ne sommes plus "en train d'évaluer une expression", mais "d'utiliser une valeur": nous utilisons toujours l'ALU, mais nous évitons de déplacer des valeurs car le résultat permettait de remplacer le paramètre. Ce type d'instruction ne peut pas être utilisé lorsque des expressions plus complexes sont nécessaires: i = 3*i + i-2ne peut pas être utilisé sur place, car il iest requis plusieurs fois.

Le troisième - même plus simple - n’envisage même pas l’idée «d’addition», mais utilise un circuit plus «primitif» (au sens de calcul) pour un compteur. L'instruction est court-circuitée, se charge plus rapidement et s'exécute immédiatement, car le réseau combinatoire requis pour moderniser un registre afin d'en faire un compteur est plus petit et donc plus rapide que celui d'un additionneur complet.

Avec les compilateurs contemporains (voir C, à présent), permettant l'optimisation du compilateur, la correspondance peut être permutée en fonction de la commodité, mais il existe toujours une différence conceptuelle dans la sémantique.

x += 5 veux dire

  • Trouver le lieu identifié par x
  • Ajoutez-y 5

Mais x = x + 5signifie:

  • Évaluer x + 5
    • Trouver le lieu identifié par x
    • Copier x dans un accumulateur
    • Ajouter 5 à l'accumulateur
  • Stocker le résultat dans x
    • Trouver le lieu identifié par x
    • Copier l'accumulateur

Bien sûr, l'optimisation peut

  • si "trouver x" n'a pas d'effets secondaires, les deux "conclusions" peuvent être effectuées une fois (et x devient une adresse stockée dans un registre de pointeur)
  • les deux copies peuvent être supprimées si ADD est appliqué à la &xplace de l'accumulateur

faisant ainsi coïncider le code optimisé avec celui- x += 5ci.

Mais cela ne peut être fait que si "trouver x" n'a pas d'effets secondaires, sinon

*(x()) = *(x()) + 5;

et

*(x()) += 5;

sont sémantiquement différentes, puisque x()les effets secondaires (admettre x()est une fonction de faire des choses étranges et de renvoyer un int*) seront produits deux fois ou une fois.

L'équivalence entre x = x + yet x += yest donc due au cas particulier où +=et =est appliquée à une valeur l directe.

Pour passer à Python, il a hérité de la syntaxe de C, mais comme il n'y a pas de traduction / optimisation AVANT l'exécution dans des langages interprétés, les choses ne sont pas nécessairement intimement liées (puisqu'il y a une étape d'analyse de moins). Cependant, un interprète peut faire référence à différentes routines d'exécution pour les trois types d'expression, en tirant parti d'un code machine différent en fonction de la manière dont l'expression est formée et du contexte d'évaluation.


Pour qui aime plus de détail ...

Chaque unité centrale a une unité ALU (unité arithmétique-logique) qui est, dans son essence même, un réseau combinatoire dont les entrées et les sorties sont "branchées" sur les registres et / ou en mémoire en fonction du code opération de l'instruction.

Les opérations binaires sont généralement implémentées en tant que "modificateur d’un registre accumulateur avec une entrée prise" quelque part ", où quelque part peut se trouver - dans le flux d’instructions lui-même (typique pour le contant manifeste: ADD A 5) - dans un autre registre temporaries: par exemple ADD AB) - dans la mémoire, à une adresse donnée par un registre (typique de la récupération de données, par exemple: ADD A (H)) - H, dans ce cas, fonctionne comme un pointeur de déréférencement.

Avec ce pseudocode, x += 5est

ADD (X) 5

alors que x = x+5est

MOVE A (X)
ADD A 5
MOVE (X) A

C'est-à-dire que x + 5 donne un temporaire qui est assigné ultérieurement. x += 5opère directement sur x.

L'implémentation réelle dépend du jeu d'instructions réel du processeur: s'il n'y a pas de ADD (.) ccode opération, le premier code devient le second: aucun moyen.

S'il existe un tel opcode et que l'optimisation est activée, la seconde expression, après avoir éliminé les déplacements inversés et ajusté l'opcode des registres, devient la première.

Emilio Garavaglia
la source
90
+1 pour la seule réponse expliquant qu'il utilisait autrefois un code machine différent (et plus efficace).
Péter Török
11
@KeithThompson C'est vrai, mais on ne peut nier que l'assemblage a eu une influence énorme sur la conception du langage C (et par la suite de tous les langages de style C)
MattDavey
51
Erm, "+ =" ne correspond pas à "inc" (mais à "ajouter"), "++" à "inc".
Brendan
11
Par "il y a 20 ans", je pense que vous voulez dire "il y a 30 ans". Et BTW, COBOL avait battu C encore 20 ans avec: AJOUTER 5 À X.
JoelFan
10
Excellent en théorie; faux dans les faits. Le x86 ASM INC ajoute seulement 1, donc cela n’affecte pas l’opérateur "ajouter et attribuer" décrit ici (ce serait une excellente réponse pour "++" et "-" si).
Mark Brackett
281

Selon votre façon de penser, il est en fait plus facile à comprendre car plus simple. Prends pour exemple:

x = x + 5 invoque le traitement mental de "take x, ajoute-en cinq, puis assigne cette nouvelle valeur à x"

x += 5 peut être considéré comme "augmenter x de 5"

Donc, ce n'est pas juste un raccourci, il décrit en fait la fonctionnalité beaucoup plus directement. Lors de la lecture de morceaux de code, il est beaucoup plus facile à comprendre.

Eric King
la source
32
+1, je suis totalement d'accord. J'ai commencé à faire de la programmation quand j'étais enfant, quand mon esprit était facilement malléable et x = x + 5me perturbait toujours. Quand j’ai commencé à apprendre les mathématiques à un âge plus avancé, cela me dérangeait encore plus. L'utilisation x += 5est beaucoup plus descriptive et prend beaucoup plus de sens en tant qu'expression.
Polynomial
44
Il y a aussi le cas où la variable a un nom long: reallyreallyreallylongvariablename = reallyreallyreallylongvariablename + 1... oh non !!! une faute de frappe
9
@ Matt Fenwick: Il n'est pas nécessaire que le nom de la variable soit long; ce pourrait être une expression de quelque sorte. Celles-ci seront probablement encore plus difficiles à vérifier et le lecteur devra faire très attention pour s’assurer qu’elles sont identiques.
David Thornley
32
X = X + 5 est une sorte de bidouille lorsque votre objectif est d'incrémenter x de 5.
JeffO
1
@Polynomial Je pense avoir aussi rencontré le concept de x = x + 5 quand j'étais enfant. 9 ans si je me souviens bien - et cela me paraissait parfaitement logique et le me semble encore parfaitement aujourd'hui et le préfère de loin à x + = 5. Le premier est beaucoup plus détaillé et je peux imaginer le concept beaucoup plus clairement - l'idée que j'assigne x à la valeur précédente de x (peu importe ce que c'est) et que j'ajoute ensuite 5. Je suppose que différents cerveaux fonctionnent de différentes manières.
Chris Harrison
48

Au moins en Python , x += yet x = x + ypeut faire des choses complètement différentes.

Par exemple, si nous faisons

a = []
b = a

alors a += [3]se traduira par a == b == [3], tandis que a = a + [3]se traduira par a == [3]et b == []. En d’autres +=termes , modifie l’objet sur place (enfin, vous pouvez définir la __iadd__méthode pour faire à peu près tout ce que vous voulez), tout en =créant un nouvel objet et en y associant la variable.

Ceci est très important lorsque vous travaillez avec NumPy , car vous vous retrouvez souvent avec plusieurs références à différentes parties d'un tableau, et il est important de vous assurer de ne pas modifier par inadvertance une partie d'un tableau qui comporte d'autres références, ou copier inutilement des tableaux (ce qui peut être très coûteux).

James
la source
4
+1 pour __iadd__: il y a des langues où vous pouvez créer une référence immuable à une structure de données mutable, où operator +=est défini, par exemple scala: val sb = StringBuffer(); lb += "mutable structure"vs var s = ""; s += "mutable variable". l'autre modifie le contenu de la structure de données tandis que cette dernière fait pointer la variable sur une nouvelle.
moutons volants
43

Cela s'appelle un idiome . Les idiomes de programmation sont utiles car ils constituent un moyen cohérent d’écrire une structure de programmation particulière.

Chaque fois que quelqu'un écrit, x += yvous savez qu'il xest incrémenté par yet non par une opération plus complexe (en tant que meilleure pratique, en règle générale, je ne mélangerais pas d'opérations plus complexes et ces raccourcis de syntaxe). Cela est le plus logique lorsque vous incrémentez de 1.

Joe
la source
13
x ++ et ++ x sont légèrement différents de x + = 1 et l'un de l'autre.
Gary Willoughby
1
@Gary: ++xet x+=1sont équivalents en C et Java (peut-être aussi en C #), mais pas nécessairement en C ++ en raison de la sémantique complexe des opérateurs. L'essentiel est qu'ils évaluent tous les deux xune fois, incrémentent la variable d'une unité et produisent un résultat correspondant au contenu de la variable après l'évaluation.
Donal Fellows
3
@Donal Fellows: La priorité est différente, ce ++x + 3n'est donc pas la même chose que x += 1 + 3. Entre parenthèses le x += 1et c'est identique. En tant que déclarations par elles-mêmes, elles sont identiques.
David Thornley
1
@ DavidThornley: Il est difficile de dire "ils sont identiques" quand ils ont tous deux un comportement indéfini :)
Courses de légèreté en orbite
1
Aucune des expressions ++x + 3, x += 1 + 3ou (x += 1) + 3n'a un comportement indéfini (en supposant que la valeur résultante "s'adapte").
John Hascall
42

Pour clarifier un peu le propos de @ Pubby, considérons someObj.foo.bar.func(x, y, z).baz += 5

Sans +=opérateur, il y a deux façons de faire:

  1. someObj.foo.bar.func(x, y, z).baz = someObj.foo.bar.func(x, y, z).baz + 5. Ce n'est pas seulement terriblement redondant et long, c'est aussi plus lent. Par conséquent, il faudrait
  2. Utilisez une variable temporaire: tmp := someObj.foo.bar.func(x, y, z); tmp.baz = tmp.bar + 5. C'est bon, mais c'est très bruyant pour une chose simple. C’est en fait très proche de ce qui se passe au moment de l’exécution, mais il est fastidieux d’écrire et le simple fait d’utiliser +=déplacera le travail vers le compilateur / interprète.

L’avantage de +=ces opérateurs est indéniable, mais s’y habituer n’est qu’une question de temps.

back2dos
la source
Une fois que vous êtes 3 niveaux plus en profondeur dans la chaîne d'objets, vous pouvez cesser de vous soucier des petites optimisations comme 1 et du code bruyant comme 2. Au lieu de cela, réfléchissez une nouvelle fois à votre conception.
Dorus
4
@Dorus: L'expression que j'ai choisie n'est qu'un représentant arbitraire de "l'expression complexe".
Ne hésitez
9
+1: C’est la principale raison de cette optimisation - elle est toujours correcte, quelle que soit la complexité de l’expression de gauche.
S.Lott
9
Mettre une faute de frappe là est une belle illustration de ce qui peut arriver.
David Thornley
21

C’est vrai que c’est plus court et plus simple, et c’est vrai que cela a probablement été inspiré par le langage d’assemblage sous-jacent, mais la pratique recommandée est qu’il empêche toute classe d’erreurs et facilite la révision du code et la sécurité. ce qu'il fait.

Avec

RidiculouslyComplexName += 1;

Comme il n'y a qu'un seul nom de variable impliqué, vous êtes sûr de ce que fait l'instruction.

Avec RidiculouslyComplexName = RidiculosulyComplexName + 1;

Il y a toujours des doutes sur le fait que les deux côtés sont exactement les mêmes. Avez-vous vu le bug? La situation est encore pire lorsque des indices et des qualificatifs sont présents.

Jamie Cox
la source
5
Cela empire encore dans les langues où les instructions d'affectation peuvent implicitement créer des variables, en particulier si les langues sont sensibles à la casse.
Supercat
14

Bien que la notation + = soit idiomatique et plus courte, ce n’est pas pour cette raison qu’elle est plus facile à lire. La partie la plus importante du code de lecture est la correspondance de la syntaxe avec le sens. Ainsi, plus la syntaxe correspond aux processus de pensée du programmeur, plus elle sera lisible (c'est aussi la raison pour laquelle le code standard est mauvais: il ne fait pas partie des idées processus, mais toujours nécessaire pour que le code fonctionne). Dans ce cas, la pensée est "incrémenter la variable x de 5", et non "que x soit la valeur de x plus 5".

Il existe d'autres cas où une notation courte est mauvaise pour la lisibilité, par exemple lorsque vous utilisez un opérateur ternaire pour lequel une ifinstruction serait plus appropriée.

tdammers
la source
11

Pour comprendre pourquoi ces opérateurs sont d’abord dans les langues de «style C», voici un extrait de K & R 1st Edition (1978), il y a 34 ans:

Indépendamment de la concision, les opérateurs d’affectation ont l’avantage de mieux correspondre à la façon dont les gens pensent. Nous disons "ajouter 2 à i" ou "incrémenter i de 2," pas "prendre i, ajouter 2, puis remettre le résultat dans i." Ainsi i += 2. En outre, pour une expression compliquée comme

yyval[yypv[p3+p4] + yypv[p1+p2]] += 2

l'opérateur d'assignation facilite la compréhension du code, car le lecteur n'a pas à vérifier minutieusement que deux expressions longues sont bien identiques ou à se demander pourquoi elles ne le sont pas. Et un opérateur d'affectation peut même aider le compilateur à produire un code plus efficace.

Je pense qu'il ressort clairement de ce passage que Brian Kernighan et Dennis Ritchie (K & R) pensaient que les opérateurs d'assignation de composé contribuaient à la lisibilité du code.

Cela fait longtemps que K & R a écrit cela, et bon nombre des «meilleures pratiques» concernant la manière dont les utilisateurs doivent écrire du code ont changé ou évolué depuis. Mais cette question programmers.stackexchange est la première fois que je me souviens de quelqu'un qui se plaignait de la lisibilité des assignations composées. Je me demande donc si de nombreux programmeurs trouvent qu’elles posent problème. Là encore, alors que je tape ceci, la question a 95 votes positifs, alors peut-être que les gens les trouveront bouleversés lors de la lecture du code.

Michael Burr
la source
9

Outre la lisibilité, ils font en réalité différentes choses: ils n'ont +=pas à évaluer son opérande gauche deux fois.

Par exemple, expr = expr + 5evalaute exprdeux fois (en supposant que ce exprsoit impur).

Pubby
la source
Pour tous les compilateurs les plus étranges, peu importe. La plupart des compilateurs sont assez intelligents pour générer le même binaire pour expr = expr + 5etexpr += 5
vsz
7
@vsz Pas si expra des effets secondaires.
Pubby
6
@vsz: En C, si expra des effets secondaires, vous expr = expr + 5 devez les invoquer deux fois.
Keith Thompson
@Pubby: s'il a des effets secondaires, il n'y a pas de problème de "commodité" ni de "lisibilité", ce qui était le but de la question initiale.
vsz
2
Mieux vaut faire attention à ces déclarations "d'effets secondaires". Lectures et écritures volatilesont des effets secondaires, et x=x+5et x+=5ont les mêmes effets secondaires quand xestvolatile
MSalters
6

Outre les avantages évidents que d'autres personnes ont très bien décrits, lorsque vous avez des noms très longs, il est plus compact.

  MyVeryVeryVeryVeryVeryLongName += 1;

ou

  MyVeryVeryVeryVeryVeryLongName =  MyVeryVeryVeryVeryVeryLongName + 1;
Andrey Rubshtein
la source
6

C'est concis.

C'est beaucoup plus court pour taper. Cela implique moins d'opérateurs. Il a moins de surface et moins de risque de confusion.

Il utilise un opérateur plus spécifique.

C'est un exemple artificiel, et je ne suis pas sûr que les compilateurs actuels l'implémentent. x + = y utilise en fait un argument et un opérateur et modifie x en place. x = x + y pourrait avoir une représentation intermédiaire de x = z où z est x + y. Ce dernier utilise deux opérateurs, addition et affectation, et une variable temporaire. L'opérateur unique explique très clairement que le côté de la valeur ne peut être autre que y et qu'il n'a pas besoin d'être interprété. Et il pourrait théoriquement exister un processeur sophistiqué doté d'un opérateur plus égal à égal à un opérateur plus rapide et d'un opérateur d'affectation en série.

Mark Canlas
la source
2
Théoriquement schmétique. Les ADDinstructions de nombreuses CPU ont des variantes qui agissent directement sur les registres ou la mémoire en utilisant d’autres registres, mémoire ou constantes comme deuxième ajout. Toutes les combinaisons ne sont pas disponibles (par exemple, ajouter de la mémoire à la mémoire), mais elles sont suffisantes pour être utiles. En tout état de cause, tout compilateur doté d'un optimiseur décent saura générer le même code pour la même x = x + yraison x += y.
Blrfl
D'où "artificiel".
Mark Canlas
5

C'est un beau langage. Que ce soit plus rapide ou non dépend de la langue. En C, c'est plus rapide car cela se traduit par une instruction pour augmenter la variable par le côté droit. Les langages modernes, y compris Python, Ruby, C, C ++ et Java, prennent tous en charge la syntaxe op =. Il est compact et vous vous y habituez rapidement. Comme vous le verrez beaucoup dans le code des autres peuples (OPC), vous pouvez aussi vous y habituer et l'utiliser. Voici ce qui se passe dans quelques autres langues.

En Python, le typage x += 5provoque toujours la création de l'objet entier 1 (bien qu'il puisse être tiré d'un pool) et l'orphelin de l'objet entier contenant 5.

En Java, cela provoque une distribution tacite. Essayez de taper

int x = 4;
x = x + 5.2  // This causes a compiler error
x += 5.2     // This is not an error; an implicit cast is done.
ncmathsadist
la source
Langues impératives modernes . Dans les langages fonctionnels (purs) x+=5a aussi peu de signification que x=x+5; par exemple dans Haskell celui - ci ne pas provoquer xd'être incrémenté de 5 - au lieu qu'elle engage une boucle de récursivité infinie. Qui voudrait un raccourci pour cela?
gauche vers le
Ce n'est pas forcément plus rapide avec les compilateurs modernes: même en C.
HörmannHH
La vitesse de +=dépend moins de la langue que du processeur . Par exemple, X86 est une architecture à deux adresses, il ne supporte que +=nativement. Une déclaration telle que a = b + c;doit être compilée a = b; a += c;car il n’ya simplement aucune instruction qui puisse placer le résultat de l’addition ailleurs que dans la place de l’un des sommands. L’architecture Power, en revanche, est une architecture à trois adresses sans commandes spéciales +=. Sur cette architecture, les instructions a += b;et a = a + b;compilent toujours au même code.
cmaster
4

Des opérateurs tels que +=sont très utiles lorsque vous utilisez une variable comme accumulateur , c'est-à-dire un total cumulé:

x += 2;
x += 5;
x -= 3;

Est beaucoup plus facile à lire que:

x = x + 2;
x = x + 5;
x = x - 3;

Dans le premier cas, conceptuellement, vous modifiez la valeur dans x. Dans le second cas, vous calculez une nouvelle valeur et l'attribuez à xchaque fois. Et même si vous n’écririez probablement jamais un code aussi simple, l’idée reste la même… l’accent est mis sur ce que vous faites pour une valeur existante au lieu de créer une nouvelle valeur.

Caleb
la source
Pour moi, c’est exactement le contraire: la première variante est semblable à la saleté sur l’écran et la seconde est propre et lisible.
Mikhail V
1
Différents traits pour différentes personnes, @MikhailV, mais si vous débutez dans la programmation, vous pourrez changer d’affichage après un certain temps.
Caleb
Je ne suis pas si novice en programmation, je pense simplement que vous vous êtes simplement habitué à la notation + = pendant une longue période et que vous pouvez donc la lire. Ce qui ne donne initialement aucune syntaxe attrayante, donc un opérateur + entouré d'espaces est objectivement plus propre que + = et ses amis, qui se distinguent à peine. Non pas que votre réponse soit incorrecte, mais il ne faut pas trop compter sur ses propres habitudes pour faire des consommations à quel point "il est facile de lire".
Mikhail V
Mon sentiment est qu'il s'agit plus de la différence conceptuelle entre accumuler et stocker de nouvelles valeurs que de rendre l'expression plus compacte. La plupart des langages de programmation impératifs ont des opérateurs similaires, il semble donc que je ne sois pas le seul à le trouver utile. Mais comme je l'ai dit, un AVC différent pour différentes personnes. Ne l'utilisez pas si vous ne l'aimez pas. Si vous souhaitez poursuivre la discussion, une discussion en ingénierie logicielle serait peut-être plus appropriée.
Caleb
1

Considère ceci

(some_object[index])->some_other_object[more] += 5

D0 tu veux vraiment écrire

(some_object[index])->some_other_object[more] = (some_object[index])->some_other_object[more] + 5
S.Lott
la source
1

Les autres réponses ciblent les cas les plus courants, mais il existe une autre raison: dans certains langages de programmation, il peut être surchargé; par exemple Scala .


Petite leçon de scala:

var j = 5 #Creates a variable
j += 4    #Compiles

val i = 5 #Creates a constant
i += 4    #Doesn’t compile

Si une classe ne définit que l’ +opérateur, x+=yc’est bien un raccourci de x=x+y.

Si une classe est surchargée +=, cependant, ils ne sont pas:

var a = ""
a += "This works. a now points to a new String."

val b = ""
b += "This doesn’t compile, as b cannot be reassigned."

val c = StringBuffer() #implements +=
c += "This works, as StringBuffer implements “+=(c: String)”."

De plus, les opérateurs +et +=sont deux opérateurs distincts (et pas seulement ceux-ci: + a, ++ a, a ++, a + ba + = b sont également des opérateurs différents); dans les langues où la surcharge d'opérateur est disponible, cela peut créer des situations intéressantes. Tout comme décrit ci-dessus - si vous surchargez l' +opérateur pour effectuer l'ajout, n'oubliez pas qu'il +=faudra également le surcharger.

moutons volants
la source
"Si une classe ne définit que l'opérateur +, x + = y est effectivement un raccourci de x = x + y." Mais sûrement cela fonctionne-t-il aussi dans l'autre sens? En C ++, il est très courant de définir d'abord +=, puis de définir a+bcomme "faire une copie de a, mettre bdessus en utilisant +=, retourner la copie de a".
leftaroundabout
1

Dites-le une fois et une fois seulement: à l' x = x + 1intérieur, je dis deux fois «x».

Mais n'écrivez jamais: 'a = b + = 1' ou nous devrons tuer 10 chatons, 27 souris, un chien et un hamster.


Vous ne devriez jamais changer la valeur d'une variable, car il est plus facile de prouver que le code est correct - voir Programmation fonctionnelle. Cependant, si vous le faites, il vaut mieux ne pas dire les choses une seule fois.

richard
la source
"ne change jamais la valeur d'une variable" Paradigme fonctionnel ?
Peter Mortensen