References
Details of how References & types work.
Immutable
Let Foo be a type.
A declaration like val my_foo: Foo = ... creates a immutable Foo, and a binding
that cannot be changed.
Assigning a immutable Foo to a var is an error:
val my_foo: Foo = .new()
var copy = my_foo // error: cannot assign a immutable value to a variable
When creating a new Foo it is saved as a immutable value:
val my_foo: Foo = Foo {
field = 0,
field = 1,
field = 2,
}
When passing a Foo to a function:
- the parameter is declared as
Foo - a immutable reference is passed
fun do_something(foo: Foo) {
// do something...
}
val my_foo: Foo = .new()
do_something(my_foo)
Mutable
TBD: syntax
Let Bar be a type.
A declaration like var my_bar: *Bar = ... creates a mutable Bar, and a binding that
can be changed.
A mutable *Bar cannot be assigned to a val:
var my_bar: *Bar = .new()
val copy = my_bar // This is an error
This is because a val should be immutable. If such assignment was allowed then one could do this:
use std
type Person = struct {
name: String,
age: i64,
}
var john = Person {
name = "John Doe",
age = 32,
}
val clone = john // mutable bind decays to a immutable one... this is not allowed
std.println(clone.age) //= 32 - the clones value
john.age = 33 // mutate og ref
std.println(clone.age) //= 33 - the underlying data of a `val` has changed!
TBD: clone syntax
Instead, if you want to do that you can clone the var instead:
var my_bar: *Bar = .new()
val copy = @clone(my_bar) // Instead of a reference to the underlying data, clone the struct.
type Person = struct {
age: i64,
}
type Family = struct {
dad: *Person, // immutable reference
mom: Person, // mutable reference
}
val f1 = Family {
dad = Person {
age = 32
}
}
var f2 = @clone(f1) // shallow clone
f2.dad.age += 1 // ok?
f2.mom.age += 1 // error: Family.mom is irreplaceable
var f2 = .{ ...f1, dad = @clone(f1.dad) }