Packages

Simple memoization for Gleam (Erlang target)

Current section

Files

Jump to
rememo_erlang src internal carpenter props.gleam
Raw

src/internal/carpenter/props.gleam

//// Props are options list used in Erlang API. Most of the time, they take the
//// form of options, that can be either atoms, or tuples of atoms (or other
//// data, like numbers, etc.). That module helps dealing with such data
//// structures while providing simple primitives to work with `Option(a)` or
//// `Bool`.
////
//// ```erl
//// % Typically in Erlang, starting an ETS table looks like this.
//// ets:new(mytable, [set, compressed, {write_concurrency, true}]).
//// ```
import gleam/bool
import gleam/dynamic/decode
import gleam/erlang/atom
import gleam/list
import gleam/option.{type Option}
pub type Props =
List(decode.Dynamic)
/// Append a prop to the props, if the value has been set. That function is made
/// to be used with a builder that set fields as optional.
pub fn append(
props: Props,
prop: Option(a),
mapper: fn(a) -> decode.Dynamic,
) -> Props {
prop
|> option.map(mapper)
|> option.map(list.prepend(props, _))
|> option.unwrap(props)
}
/// Append a prop to the props, if the value is true. That function is made
/// to be used with a builder that set fields as false by default.
pub fn append_if(
props: Props,
prop: Bool,
mapper: fn() -> decode.Dynamic,
) -> Props {
use <- bool.guard(when: !prop, return: props)
[mapper(), ..props]
}
/// Helper to generate an atom. Instead of continuously generating it, and
/// coercing it as `Dynamic`, `atom` directly generate a dynamic atom.
pub fn atom(name: String) -> decode.Dynamic {
let value = atom.create(name)
coerce(value)
}
/// Helper to generate a pair of atoms, directly from strings. Simplify code
/// and easy generating of atoms.
pub fn pair(prop: String, value: a) -> decode.Dynamic {
let prop = atom(prop)
let value = coerce(value)
coerce(#(prop, value))
}
/// Used to replace `dynamic.from`, which is now deprecated. Because we're
/// working with Erlang functions that could be highly dynamic, it's often
/// necessary to convert our data structure to `Dynamic`.
@external(erlang, "carpenter_ffi", "coerce")
fn coerce(a: a) -> decode.Dynamic