Just curious why? I can live with the language design decision, but it seems to often force me to create a local variable which is verbose when all I want to do is set a class variable and return it. If I return the class variable instead, there could be some threading issues that the return value is different then what I just set. I think even smalltalk allowed a set on the last line which was returned.
I might be wrong about the reason but I think that the kotlin designers don’t like assignments within other expressions
foo(a = bar())
if(a = foo()) {}
They lifted that restriction for when
expressions but AFAIK this is a specia case. Maybe return
could be another special case.
According to Kotlin In Action (by members of the Kotlin development team), having assignments become statements
helps avoid confusion between comparisons and assignments, which is a common source of mistakes.
In my experience, the most common source of confusion is in if (…)
and while (…)
conditions.⠀In particular, it’s far too easy to type =
when you mean ==
.⠀In languages like C, where any type of value can be a condition, that’s quite likely not to generate a compile error, but instead to assign something unexpectedly, and then test whether the value assigned was non-zero — which is highly likely to cause a bug.
In fact, it’s a common enough problem that at least two coding conventions have arisen to try to avoid it.⠀(It’s common to compare a variable with a constant, and in those case swapping them to put the constant first and the variable second will usually generate a compile error if you omit the second =
symbol — at the cost of making the code harder to read. Also, you can signal to some compilers and other tools that you intend an assignment by enclosing it in a second set of parens; those tools can then give a warning or error if they find an assignment in only one set.)
Java is a bit safer in that regard, as it requires conditions to be boolean values.⠀But it’s still possible to hit the bug, if the value being compared is a boolean.⠀By disallowing assignments in conditions, Kotlin is completely free from it.
There’s also the issue of readability generally.⠀Embedding an assignment within a complex expression can be tempting, as it can avoid a some duplication or a temporary variable — but it can be very hard to read.⠀Kotlin pretty much forces you to rearrange the code into an order that’s more straightforward (if perhaps slightly longer).
(There are, of course, ways around this; in particular, you can embed an assignment in an also{…}
call within an expression to get much the same effect.⠀That’s still hard to read, though the braces may make it slightly more obvious.⠀And the .also{…}
isn’t something you can get from a simple typo!)
A very special case, AIUI: it needs to be of the form when (var myVar = … )
— so the assignment needs to be at the start of the condition, at the top level (i.e. not within parens or braces), and preceded by var
(which would otherwise be invalid within an expression).
That’s clear to the reader, has no ambiguity or risk of unexpected effects, and prevents many of the more, er, creative uses of assignment in expressions.
(Of course, if the C family of languages had inherited the Pascal style of operator, i.e. =
for equality and :=
for assignment, things might be rather clearer and we might not be stuck with such workarounds — nor with abominations such as ===
operators!⠀But hindsight is always, er, 2020…)
Another reason is that in function calls, assignment expressions would be indistinguishable from passing named parameters, e.g.
foo(bar = 1) // is it an assignment to 'bar' variable or a named parameter 'bar'?
I learned something. Thanks!
In functional style, creating a variable is usually not the right approach. For example I would probably consider doing something like:
return theNewValue
.also { myClassVariable = it }
I’ll add my two cents on this as well:
Although you can use other ways of avoiding the local variable, make sure you pause to consider if it adds value to have the named variable included.
A lot of times, the single extra line gives you more clarity–even if it only serves to name that value.