Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

Assignment Notation

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 this: Demo Zoo: Assignment, Vars, & Consts.

Assignment Operations

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

Considerations

Mathematical Notation

Using = for an assignment is mathematically very unsatisfactory, code such as x = x + 1 mathematically does not make sense.

Discourage Mutation

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
tail_call(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
tail_call(next)

or maybe using the left-to-right order

if x < 999
  x + 1
else
  0
=: next
tail_call(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 as expressions.

Future Fuzion Proposal

  • Assignment: set v := expr, where set indicates to set an existing field. Alternatively expr =: set v
  • Declaring a new field: v type := expr or expr =: v type.
  • Declaring a new field with type inference: v := expr or expr =: v.
  • Comparison of two values: a = b
  • Declaration of a routine with result type inference: a => b

Open Questions

Will the 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 as var in the declaration such that we get var x i32 := 0 to declare a mutable field x?

Python, Scala

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 operator := was introduced.