Views
On occasion, it can be useful for non-local code to provide a new value for a locally-declared value.
Views implement this in a safe, lexically-scoped way.
Basic use
A view is created by wrapping a declared name in curly braces { }.
let total : num = 5
let total_view : {num} = {total}
Views cannot be passed out of the scope where the original value is defined, unless the original value is passed out at the same time.
-- This is not allowed.
let total_view = (
let total = 5
{total}
)
-- This is allowed.
let (total, total_view) = (
let total = 5
(total, {total})
)
Once a view has been created, it can be be used to shadow the original declaration by using view syntax in a capture.
let increase = fn(
.by delta : num
.total : {num}
.count : {num}
) (
let {total} = total + delta
let {count} = count + 1
()
)
-- After this tuple evaluates, the_total = 8, and the_count = 3
let (the_total, the_count) = (
let my_total = 0
let my_count = 0
increase(.by 1, .total {my_total}, .count {my_count})
increase(.by 5, .total {my_total}, .count {my_count})
increase(.by 2, .total {my_total}, .count {my_count})
(my_total, my_count)
)
Shadowing
Note that assigning a value to a view does not mutate the viewed value. It explicitly creates a new declaration for the viewed value.
This means you may keep a view to the original value to retain access to it after it has been re-assigned.
let bump = fn(.x : {num}) (
let {x} = x + 1
)
let counter = 0
let original_view = {counter}
----
This bump() creates a new `counter` declaration and assigns it the new value.
However, `original_view` still views the previous `counter`.
This lets you shadow a value without losing access to the old value in the process.
----
bump(original_view) -- `let counter = 0 + 1`
bump(original_view) -- still `let counter = 0 + 1`
bump(original_view) -- still `let counter = 0 + 1`
---
You must create a new view if you want to continue updating the value cumulatively.
---
bump({counter}) -- `let counter = 1 + 1`
bump({counter}) -- `let counter = 2 + 1`
bump({counter}) -- `let counter = 3 + 1`