Atom
type Atom<T> @abstract =
var value : T
let callbacks = StdList.new
def subscribe (f : T * T -> Unit) =
callbacks.add f
Token { callbacks.remove f }
Атом это контейнер, хранящий значение и оповещающий о его изменениях.
type MutAtom<T> @[mut_of Atom] =
inherit Atom<T>
def set (x : T) =
if x == value then return
let prev_x = value
value = x
for f in callbacks do
f prev_x x
MutAtom это изменяемая версия типа Atom. Имена MutAtom и mut Atom являются синонимами.
type Token =
let f : Unit -> Unit
let mut is_discarded = false
def discard =
assert not is_discarded
is_discarded = true
f ()
Метод subscribe возвращает объект типа Token, позволяющий отменить подписку.
var obs position = Vector3.new
var obs origin = Vector3.new
val global_position@obs = origin@obs + position@obs
let token = position@atom
|> subscribe { prev_v v -> println "position changed from $prev_v to $v" }
Для привязок position и origin создаются объекты MutAtom<Vector3>. Значение global_position будет пересчитано при каждом их изменении.
Модификатор @atom возвращает контейнер. Фигурные скобки определяют замыкание.
let tuple_atom = (position@atom, origin@atom) |> to_atom
let sum@atom = tuple_atom.map { u, v -> u + v }
to_atom преобразовывает кортеж атомов в атом кортежей. Привязка tuple_atom имеет тип Atom<(Vector3, Vector3)>.
Метод map типа Atom получает в качестве аргумента замыкание типа (Vector3, Vector3) -> Vector3 и возвращает объект Atom<Vector3>. Модификатор @atom на привязке sum скрывает контейнер. Доступ к sum будет возвращать значение поля value контейнера, а присваивание вызовет метод set.
Запятая между u и v в списке параметров замыкания означает, что это элементы кортежа. Скобки не обязательны, если кортеж является единственным параметром.