Reactive programming

type Border @mut =
    inherit Control

    var obs left : u32 = 0
    var obs right : u32 = 0
    var obs up : u32 = 0
    var obs down : u32 = 0
    var obs content : Option<Control> = None

The obs modifier creates a container of type mut Atom<T> that can send notifications when a value changes.

let is_aligner = content@atom.map { case _ of
    None -> false
    Some control -> control is Aligner }

content@atom returns a container, map is a method defined for the Atom<T>.

let thickness = (left@atom, right@atom, up@atom, down@atom) |> to_atom

Tuple of atoms can be transformed into an atom of tuples, the type of thickness is Atom<(u32, u32, u32, u32)>.

val memory@atom = (width@atom, height@atom, thickness)
                  |> to_atom
                  |> map { self (width, height, thickness) ->
                      if width == 0 || height == 0
                      then None
                      else Some (width, height, thickness) }
                  |> option_map { self (width, height, (left, right, up, down)) ->
                      ...
                      MeshMemory.from_quads quads.as_slice }

Because of the @atom modifier, binding memory has a type Option<MeshMemory> and not Atom<Option<MeshMemory>>.

let obs size : u32 = 10
let obs factor : f32 = 0.8

margin.up@obs = size@obs as f32 * factor@obs |> as<u32>

The margin.up field will be updated if size or factor changes.