Skip to content

Latest commit

 

History

History
191 lines (136 loc) · 2.85 KB

mutation.md

File metadata and controls

191 lines (136 loc) · 2.85 KB

Mutable variables can be defined using mut and referenced as usual.

a mut = 1
a

1

To mutate a mutable variable, use @.

a mut = 1
a@ = a + 1
a

2

This works inside patterns too!

a mut = 1
b mut = 2
[a@, b@] = [b, a]
[a, b]

[2, 1]
a mut = 1
b mut = 2
[a@, c] = [b, a]
[a, b, c]

[2, 2, 1]

To pass a mutable reference to a function, mark the argument as mut and pass the reference with @.

a mut = 1
set = (var mut, val) { var@ = val }
set(a@, 2)
a

2

Every mut binding in the function must be paired with an @ reference in the call site.

a mut = 1
set = (var mut, val) { var@ = val }
set(a, 2)
a

Expected a mutable reference, found: 1

Expected a mutable reference, found: i64
a mut = 1
set = (var, val) { var@ = val }
set(a@, 2)
a

May not mututate immutable binding: var
a mut = 1
set = (var, val) { }
set(a@, 2)
a

Expected a value containing no mutable references, found: 1/ref[i64]

Expected a value containing no mutable references, found: ref[i64]

If a mutable reference contains an object, mutable references may be constructed to fields of that object.

a mut = [b: 1]
a.b@ = 2
a

[b: 2]

['b': 2]
a mut = [b: 1]
set = (var mut, val) { var@ = val }
set(a.b@, 2)
a

[b: 2]

['b': 2]

TODO Mutable references never alias - setting the value of one mutable variable will never change the value of another mutable variable. To enforce this, all of the mutable arguments to a function call must be disjoint.

a mut = [b: 1, c: 2]
swap = (x mut, y mut) { 
  [x@, y@] = [y, x]
}
swap(a.b@, a.c@)
a

[b: 2, c: 1]

['b': 2, 'c': 1]
a mut = [b: 1, c: 2]
swap = (x mut, y mut) { 
  [x@, y@] = [y, x]
}
swap(a.b@, a.b@)
a

[b: 1, c: 2]

['b': 1, 'c': 2]

Only the mutable arguments are required to be disjoint - other arguments may overlap.

a mut = [b: 1, c: 2]
set = (var mut, val) { var@ = val }
set(a.b@, a.b)
a

[b: 1, c: 2]

['b': 1, 'c': 2]

Mutable references are 2nd-class - they cannot be assigned or returned.

a mut = 1
a@

Expected a value containing no mutable references, found: 1/ref[i64]

Expected a value containing no mutable references, found: ref[i64]
a mut = 1
b = a@

Expected a value containing no mutable references, found: 1/ref[i64]

Expected a value containing no mutable references, found: ref[i64]
a mut = 1
b = [a@]

Expected a value containing no mutable references, found: [1/ref[i64]]

Expected a value containing no mutable references, found: struct[ref[i64]]

Assigning to a mutable reference may not change the type of underlying variable:

a mut = 1
a@ = 'foo'

Expected i64, found string
a mut = [b: 1]
a.b@ = 'foo'

Expected i64, found string