apply
Cross-runtime dynamic function invocation for Erlang and JavaScript.
Resolve functions by string path in the target runtime and call them:
guard_type enforces a return type via a default anchor,
guard_not treats a specific value as failure. Error messages share a
unified path/arity + reason style on both targets.
Values
pub fn get_erl_func(
raw_path: String,
erl_arity: Int,
) -> Result(any, String)
Fetch an Erlang function reference (Erlang target only).
Accepts "Module:Function", or a bare function name which is prefixed
with erlang:. Returns Ok(fun) on success; always returns a runtime
error on the JavaScript target.
let assert Ok(map) = apply.get_erl_func("lists:map", 2)
Errors include the arity, e.g.
"erlang:length/2 is not exported in erlang (existing arities: 1)".
pub fn get_js_obj(raw_script: String) -> Result(any, String)
Fetch a JavaScript runtime object or function (JavaScript target only).
Takes a dotted path such as "Math.PI" or "console.log".
let assert Ok(3.141592653589793) = apply.get_js_obj("Math.PI")
let assert Ok(max) = apply.get_js_obj("Math.max")
Always returns a runtime error on the Erlang target.
pub fn guard_not(
raw_path: String,
args: args_tuple,
error_value: a,
) -> Result(any, String)
Dynamically invoke a runtime function, treating a specific value as failure.
raw_path:"Module:Function"on Erlang,"object.property"on JavaScript.args: must be a tuple; elements are spread as call arguments in order.error_value: the exact value the function uses to signal failure — JSundefined/null, Erlangfalse/nil/{error, _},-1,"", …
Returns Result(any, String):
Ok(value)- the call succeeded and the result is not the error value (any type; interpret it yourself)Error(message)- bad path, target not callable, exception caught, or the result equalserror_value
This checks values, not types — the result comes back as any. Use
guard_type when you need a type guarantee instead.
Passing Nil as error_value is the natural way to fetch platform-local
values (Erlang references, JavaScript objects): anything except nil/
undefined comes back as Ok, so no type signature is bent:
let assert Ok(ref) = apply.guard_not("erlang:make_ref", #(), Nil)
let assert Ok(True) = apply.guard_type("erlang:is_reference", #(ref), False)
let assert Error(msg) = apply.guard_not("erlang:is_atom", #(1), False)
// msg == "erlang:is_atom/1 returned false (guard error value)"
pub fn guard_type(
raw_path: String,
args: args_tuple,
default: a,
) -> Result(a, String)
Dynamically invoke a runtime function with a strict type check.
raw_path:"Module:Function"on Erlang,"object.property"on JavaScript.args: must be a tuple; elements are spread as call arguments in order.default: pins the expected return type; the call result is type-checked against it at runtime before being returned.
Returns Result(a, String) where a is the type of default:
Ok(value)- the call succeeded and the result has the same runtime type asdefaultError(message)- bad path, target not callable, exception caught, or the result type does not matchdefault
apply.guard_type("erlang:length", #([1, 2, 3]), 0) // Ok(3) (Int)
apply.guard_type("Math.max", #(1, 5), 0) // Ok(5) (Int)
apply.guard_type("erlang:is_atom", #(1), 0)
// Error("erlang:is_atom/1 returned false (type boolean), expected type int")
The type judgement rules are shared with unwrap/2 (see there). If you
only care about which value the function uses as its failure signal (not
its type), use guard_not instead.
pub fn platform_name() -> String
The current runtime platform.
Returns "erlang" on the Erlang target and "javascript" on the
JavaScript target.
pub fn unwrap(value: any, default: a) -> a
Type-checked fallback for a dynamic value.
Functions fetched from a runtime (get_js_obj / get_erl_func) can return
more than one type: an Int, a Float, a Bool, a String, a list -
or even an abnormal value such as JS undefined/null or Erlang
false/nil/{error, _}. Gleam cannot know which one you got, so it types
the value as any. unwrap/2 settles that:
- same runtime type as
default->value(already of typea) - otherwise ->
default
let int = apply.unwrap(5, 0) // 5 (Int 与 0 同类型)
let text = apply.unwrap(5, "") // "" (Int ≠ String,回退默认值)
pub fn unwrap_not(value: any, error_value: a) -> Result(any, a)
Value-anchor check for a dynamic value — the value-level guard_not.
If value is not the error_value, returns Ok(value) (any type);
if it equals error_value, returns Error(error_value).
Unlike unwrap (which compares types and falls back), this compares
values and reports the match as an error. Unlike guard_not (which
resolves and calls a path), this just checks a value you already hold.
let assert Ok(5) = apply.unwrap_not(5, False) // 5 ≠ false
let assert Error(False) = apply.unwrap_not(False, False)
let assert Error(Nil) = apply.unwrap_not(Nil, Nil)