I changed the assignments several times — and it is not surprising when you consider the various approaches of the programming languages. Lately I reverted them to “statements only” because of Swift, to change it back to the expressions because of PHP. However the argument statements vs. expressions was not my only concern — I have learned (from Fluent Python by Luciano Ramalho) that Python switches the meaning of the compound assignment depending which operator was implemented in a given type.
m += u;
m value be changed in place or will a new object be created and bound to
m? It is impossible to say without looking at the
m type implementation. Not that I was about to make similar mistake, but I realized that compound assignment should scream its meaning so there were no doubts what it does.
I also have read an interesting complaint about the assignment symbol itself:
A notorious example for a bad idea was the choice of the equal sign to denote assignment. It goes back to Fortran in 1957 and has blindly been copied by armies of language designers. Why is it a bad idea? Because it overthrows a century old tradition to let “=” denote a comparison for equality, a predicate which is either true or false.— Niklaus Wirth, Good Ideas, Through the Looking Glass
I understand the point but I don’t share the reservation — we don’t have the freedom of the blackboard, only the keyboard with just a few symbols. The tool dictates the possibilities.
Enough about the problems — let’s talk about solutions. The assignment is written all over the code — so it has to be single character, for me there is no debate here really, besides there are too many languages which use this syntax, the winner is:
s = "hello world";
I would like to compare values with operators like “
>” or “
<=”, so testing value equality has to be written with:
if s == "hello world" then ...
Here is the rub — assigning reference is done with single “equal” sign, while testing the value is done with the doubled sign. Well, far from perfect I know, I know.
Optional assignments work only within conditional structures:
if s ?= tryHello() then ...
null — variable
s will not be altered and the true branch of
if will not be executed. When
tryHello returns real value, the reference to that value will be assigned to
s and the execution will proceed.
Assignments used as an expressions proved to be useful, however the usual syntax leads to errors and countermeasures such as yoda conditions. Scala ¹ and Swift ² are examples of the languages that dropped the support for assignment expressions, but why remove semantics when the problem lies in syntax:
a = b := c; // with expression b = c; // just statements a = c;
Please note that there is just one edit distance point between “
=” and “
==”, while there are two points between ”
:=” and “
==”. It does not guarantee the safety, but it should be sufficient protection against misspelling.
I would like to remove compound assignments to be crystal clear there is no alteration of the value in place (there should be another operator for this). Of course repeating left hand side of the assignment (with possible subexpressions) is a nasty thing to do. Unless ³:
msg = "world"; msg = "hello " + $;
On the expense of little more typing user will get way more power — I think it is a fair exchange.
¹ What is the motivation for Scala assignment evaluating to Unit. It seems Scala was supposed to evaluate assignments to their left hand side value, not right.
² What was the reason for Swift assignment evaluation to void — do you know the answer?
³ The idea is not mine (as usual), but I cannot recall where did I read this, I will update this post as soon as I find out.