What should the assignment and definition operators be? Odersky started a
discussion about switching to
:= for assignments in
Scala: Use :=
for Assignment. A video by Context Free discusses
Zoo: Assignment, Vars, & Consts.
There are basically these operations
- Assignment to a variable, in Java
a = b;
- Declaration of a new variable, in Java
type a = b;
- Declaration of a new variable with type inference, in Java
var a = b;
- Comparison of two values, in Java
a == b
- Declaration of a routine with result type inference, in Fuzion so far
a => b
= for an assignment is mathematically very unsatisfactory,
code such as
x = x + 1 mathematically does not make sense.
Assignments are mutations of a variable and should be avoided, declarations should be preferred whenever possible.
left-to-right execution order
Assignments and declarations are the wrong way around.
sum := a + b + c
A notation that puts the variable at the end represents the flow of execution better.
a + b + c =: sum
Assignments for Control Flow
A common reason for assignments are values depending on control flow.
next i32 if x < 999 next = x + 1 else next = 0 tailCall(next) -- some use of next
One way to avoid this is allowing statement results that can be used in declarations
next := if x < 999 x + 1 else 0 tailCall(next)
or maybe using the left-to-right order
if x < 999 x + 1 else 0 =: next tailCall(next)
Assignment as Expression with Result
Having assignments produce a result is an awful idea from a functional perspective. An assignment as part of an expression introduces a side-effect. Even if only used as a declaration of a new variable, this variable can be hidden deep in an expression and together with lazy operations, it additionally results in complex visibility rules.
The most convincing example in the big discussion about Python 3.8's walrus operator that I have seen is this loop
# Python code: chunk = file.read(8192) while chunk: process(chunk) chunk = file.read(8192)
Which can be simplified to
# Python code: while chunk := file.read(8192): process(chunk)
For Fuzion, the powerful loop syntax instead should allow
for chunk := file.read(8192) while chunk? process(chunk)
which avoids the second call to
file.read. Disregarding the
braces, the code essentially adds
chunk once, which is so little
additional typing that it does not justify the complexity of having assignments
Future Fuzion Proposal
set v := expr, where
setindicates to set an existing field. Alternatively
expr =: set v
- Declaring a new field:
v type := expror
expr =: v type.
- Declaring a new field with type inference:
v := expror
expr =: v.
- Comparison of two values:
a = b
- Declaration of a routine with result type inference:
a => b
set keyword in an assignment make the definition more popular?
Are the left-to-right versions too confusing or could they turn out to be useful once one got used to this syntax?
So far, a field is immutable if there is no assignment to it except for the
initial assignment. Together with the fact that assignments are not allowed
outside of the feature that declares the field, the compiler can easily
distinguish mutable from immutable fields. However, do we need better syntax to
make this obvious for the human eye, e.g., requiring a keyword such
var in the declaration such that we get
var x i32 :=
0 to declare a mutable field
The assignment operator causes big emotional discussions. Odersky had to step
back, Guido van Rossum gave up his position as BDFL for Python when the walrus
:= was introduced.