bright
Types
Functions
pub fn compute(
bright: #(Bright(a, b), Effect(c)),
compute_: fn(a, b) -> b,
) -> #(Bright(a, b), Effect(c))
Derives data from the data state, and potentially the current computed
state. compute will run at every render, so be careful with computations
as they can block paint or actors.
pub fn update(model: Bright(data, computed), msg: Msg) {
use model <- bright.start(model)
model
|> bright.update(update_data(_, msg))
|> bright.compute(fn (d, c) { Computed(..c, field1: computation1(d)) })
|> bright.compute(fn (d, c) { Computed(..c, field2: computation2(d)) })
|> bright.compute(fn (d, c) { Computed(..c, field3: computation3(d)) })
}
pub fn computed(bright: Bright(a, b)) -> b
Extracts computed state from Bright.
pub fn view(model: Bright(data, computed)) {
let computed = bright.computed(model)
html.div([], [
// Use computed here.
])
}
pub fn data(bright: Bright(a, b)) -> a
Extracts data state from Bright.
pub fn view(model: Bright(data, computed)) {
let data = bright.data(model)
html.div([], [
// Use data here.
])
}
pub fn init(data data: a, computed computed: b) -> Bright(a, b)
Creates the initial Bright. data & computed should be initialised with
their correct empty initial state.
pub fn lazy_compute(
bright: #(Bright(a, b), Effect(c)),
selector: fn(a) -> d,
compute_: fn(a, b, d) -> b,
) -> #(Bright(a, b), Effect(c))
Derives data like compute lazily. lazy_compute accepts a
selector as second argument. Each time the selector returns a different data
than previous run, the computation will run. Otherwise, nothing happens.
The computation function will receive data, computed and the selected
data (i.e. the result from your selector function), in case accessing the
selected data is needed.
pub fn update(model: Bright(data, computed), msg: Msg) {
use model <- bright.start(model)
model
|> bright.update(update_data(_, msg))
// Here, e is always the result data.field / 10 (the result from selector).
|> bright.lazy_compute(selector, fn (d, c, e) { Computed(..c, field1: computation1(d, e)) })
|> bright.lazy_compute(selector, fn (d, c, e) { Computed(..c, field2: computation2(d, e)) })
|> bright.lazy_compute(selector, fn (d, c, e) { Computed(..c, field3: computation3(d, e)) })
}
/// Use it with lazy_compute to recompute only when the field when
/// { old_data.field / 10 } != { data.field / 10 }
fn selector(d, _) {
d.field / 10
}
pub fn lazy_schedule(
bright: #(Bright(a, b), Effect(c)),
selector: fn(a) -> d,
schedule_: fn(a, b, d) -> Effect(c),
) -> #(Bright(a, b), Effect(c))
Plugs in existing data like schedule lazily. lazy_schedule accepts
a selector as second argument. Each time the selector returns a different data
than previous run, the computation will run. Otherwise, nothing happens.
The scheduling function will receive data, computed and the selected
data (i.e. the result from your selector function), in case accessing the
selected data is needed.
pub fn update(model: Bright(data, computed), msg: Msg) {
use model <- bright.start(model)
model
|> bright.update(update_data(_, msg))
// e is equal to d.field / 10 (the result from selector).
|> bright.lazy_schedule(selector, fn (data, computed, selected) {
use dispatch <- effect.from
case d.field == 10 {
True -> dispatch(my_msg)
False -> Nil
}
})
}
/// Use it with lazy_schedule to recompute only when the field when
/// { old_data.field / 10 } != { data.field / 10 }
fn selector(d, _) {
d.field / 10
}
pub fn schedule(
bright: #(Bright(a, b), Effect(c)),
schedule_: fn(a, b) -> Effect(c),
) -> #(Bright(a, b), Effect(c))
Plugs in existing data and computed state, to issue some side-effects,
when your application needs to run side-effects depending on the current state.
pub fn update(model: Bright(data, computed), msg: Msg) {
use model <- bright.start(model)
model
|> bright.update(update_data(_, msg))
|> bright.schedule(model, fn (data, computed) {
use dispatch <- effect.from
case data.field == 10 {
True -> dispatch(my_msg)
False -> Nil
}
})
}
pub fn start(
bright: Bright(a, b),
next: fn(#(Bright(a, b), Effect(c))) ->
#(Bright(a, b), Effect(c)),
) -> #(Bright(a, b), Effect(c))
Start the Bright update cycle. Use it as a way to trigger the start of Bright
computations, and chain them with other bright calls. start handles all
of the hard work, of turning a Bright(data, computed) into a
#(Bright(data, computed), Effect(msg)), and will take care that your
Bright(data, computed) is always consistent over multiple update cycles.
pub fn update(model: Bright(data, computed), msg: Msg) {
// Starts the update cycle, and returns #(Bright(data, computed), Effect(msg)).
use model <- bright.start(model)
bright.update(model, update_data(_, msg))
}
pub fn step(
bright: #(Bright(a, b), Effect(c)),
next: fn(Bright(a, b)) -> #(d, Effect(c)),
) -> #(d, Effect(c))
Allows to run multiple update on multiple Bright in the same update cycle.
Every call to step with compute a new Bright, and will let you chain the
steps.
pub type Model {
Model(
fst_bright: Bright(data, computed),
snd_bright: Bright(data, computed),
)
}
fn update(model: Model, msg: Msg) {
use fst_bright <- bright.step(update_fst(model.fst_bright, msg))
use snd_bright <- bright.step(update_snd(model.snd_bright, msg))
#(Model(fst_bright:, snd_bright:), effect.none())
}
pub fn unwrap(bright: Bright(a, b)) -> #(a, b)
Extracts data & computed states from Bright.
pub fn view(model: Bright(data, computed)) {
let #(data, computed) = bright.unwrap(model)
html.div([], [
// Use data or computed here.
])
}
pub fn update(
bright: #(Bright(a, b), Effect(c)),
update_: fn(a) -> #(a, Effect(c)),
) -> #(Bright(a, b), Effect(c))
Update data & effects during update cycle. Use it a way to update your data
stored in Bright, and chain them with other bright calls.
pub fn update(model: Bright(data, computed), msg: Msg) {
use model <- bright.start(model)
// Run an update, and returns #(Bright(data, computed), Effect(msg)).
bright.update(model, update_data(_, msg))
}