Assignments
An assignment sets a field to the result of an expression.
Initial Values
In Fuzion, static code analysis ensures that no field is called before an initial value has been assigned to the field.
A program that may access uninitialized fields does not compile:
Immutable fields
By default fields are immutable. This means no value may be assigned to a field except for the assignment of the initial value. In most situations, it is fully sufficient to work with immutable fields.
Imagine you want to write a loop that calculates the sum of all the elements
in an array by iterating over the array and adding up the values of all elements in
a variable s. The following code does this using an immutable
loop index variable:
This code, in effect, creates a new instance of s for each
loop iteration. Each of these instances is immutable.
Mutability using mutate Effect
CAVEAT: Using mutable fields has a number of disadvantages, in particular, the field may no longer be used by multiple threads and functions accessing that field become impure, i.e., their result depends not only on the input parameters but also on the current value of the mutable field. This makes analysis of the code hard and prohibits optimizations that would be possible otherwise.
Mutable fields can be realized in Fuzion using effects, in particular
the mutate effect permits repeated modification of a value. A
field x that may be mutated using this effect can be created via a
call to mut giving the initial value a of the
field:
If you analyse this code using the button Effects!, you will see that
this code uses the mutate effect. In fact, mut is
just a shorthand for mutate.env.var, i.e. creating a mutable
field requires an installed mutate effect.
Once created, the field may be updated to a value b using:
x <- b
A more useful example using a mutable field cn to cache the
result of a function call is given here:
Reading a mutable field usually does not require an explicit call to
get. However, get still exists and is required in
contexts where no target type is known, for example when a type parameter is
inferred from the arguments:
Without .get the compiler infers two different types for the
type parameter of infix =: i64 for the left hand-side
and mutate.new.i64 for the right hand-side. A corresponding error
would be reported.
The following sections of this tutorial will present techniques to avoid field updates. Using these techniques will enable compiler optimizations that are not possible with mutable fields. Immutable fields will also be a basic prerequisite for Fuzion's safe concurrency model.