std/dynamic
Import with import std/dynamic.
Exports
Section titled “Exports”type Dynamic
Section titled “type Dynamic”type Dynamic
Opaque wrapper for a value of unknown shape returned by an extern function or decoded from an external source such as JSON, YAML, RPC payloads, or database rows.
Dynamic values are produced by externs that declare Dynamic in their
return type. Pure Nomi code cannot construct one directly. To pass a typed
Nomi value to host code as a dynamic value, call an extern that accepts a
Dynamic argument and let the runtime marshal it for the host.
Inspect via Dynamic.field/index/path navigators and
Dynamic.as_string/as_int/… extractors. Each step returns
Result<_, DecodeError> with a structured path; chain with try to
propagate.
Dynamic.field
Section titled “Dynamic.field”fn field(d: Dynamic, name: String): Result<Dynamic, DecodeError>
type function on Dynamic
Drill into a struct/dict-shaped Dynamic by field name. Fails with
expected="object with field <name>" if d is a dict but doesn’t have the
field, or expected="object" if d is not a dict at all.
Dynamic.index
Section titled “Dynamic.index”fn index(d: Dynamic, i: Int): Result<Dynamic, DecodeError>
type function on Dynamic
Drill into a list-shaped Dynamic by zero-based index. Fails with
expected="list with at least <i+1> elements" if d is a list but the index
is out of bounds, or expected="list" if d is not a list at all.
Dynamic.path
Section titled “Dynamic.path”fn path(d: Dynamic, dotted: String): Result<Dynamic, DecodeError>
type function on Dynamic
Convenience: dotted-path navigator. Dynamic.path(d, "a.b.c") is
equivalent to
d |> Dynamic.field("a") |> try |> Dynamic.field("b") |> try |> Dynamic.field("c").
Does NOT support index notation (use index directly for lists). Empty
segments (e.g. "a..b") error.
Dynamic.as_string
Section titled “Dynamic.as_string”fn as_string(d: Dynamic): Result<String, DecodeError>
type function on Dynamic
Extract a Dynamic as a String. Err on type mismatch.
Dynamic.as_int
Section titled “Dynamic.as_int”fn as_int(d: Dynamic): Result<Int, DecodeError>
type function on Dynamic
Extract a Dynamic as an Int. Accepts integer-shaped Floats (e.g. JSON’s number 36.0) but rejects values with a fractional part.
Dynamic.as_float
Section titled “Dynamic.as_float”fn as_float(d: Dynamic): Result<Float, DecodeError>
type function on Dynamic
Extract a Dynamic as a Float. Accepts Ints (widening) and Floats.
Dynamic.as_bool
Section titled “Dynamic.as_bool”fn as_bool(d: Dynamic): Result<Bool, DecodeError>
type function on Dynamic
Extract a Dynamic as a Bool. Err on type mismatch.
Dynamic.as_list
Section titled “Dynamic.as_list”fn as_list(d: Dynamic): Result<List<Dynamic>, DecodeError>
type function on Dynamic
Extract a Dynamic as List<Dynamic> — each element is still wrapped, so
per-element decoding composes through as_list. Err if d is not a list.
Dynamic.as_dict
Section titled “Dynamic.as_dict”fn as_dict(d: Dynamic): Result<Map<String, Dynamic>, DecodeError>
type function on Dynamic
Extract a Dynamic as Map<String, Dynamic> — each value is still
wrapped, so per-value decoding composes. Err if d is not a dict/object.
Dynamic.null?
Section titled “Dynamic.null?”fn null?(d: Dynamic): Bool
type function on Dynamic
True iff d represents a null/nil value at the source (JSON null, Go nil, etc.). Never errors.
Dynamic.has?
Section titled “Dynamic.has?”fn has?(d: Dynamic, name: String): Bool
type function on Dynamic
True iff d is a dict and contains the named field. False otherwise (including when d is not a dict). Never errors.
Dynamic.as_maybe
Section titled “Dynamic.as_maybe”fn as_maybe<T>(d: Dynamic, sub: (Dynamic) -> Result<T, DecodeError>): Result<Maybe<T>, DecodeError>
type function on Dynamic
Apply sub to d only if d is non-null. Null -> Ok(None); present ->
Ok(Some(try sub(d))).
The ergonomic helper for JSON’s ubiquitous nullable fields.
d |> Dynamic.as_maybe(Dynamic.as_string) |> try // -> Maybe<String> from the value (or None if null).
Dynamic.at_field
Section titled “Dynamic.at_field”fn at_field<T>(d: Dynamic, name: String, sub: (Dynamic) -> Result<T, DecodeError>): Result<T, DecodeError>
type function on Dynamic
Navigate into a struct/dict field AND apply a sub-decoder, accumulating the path segment on any error the sub-decoder returns. The chain
d |> Dynamic.at_field("user", |inner| inner |> Dynamic.at_field("address", |inner2| inner2 |> Dynamic.at_field("zip", Dynamic.as_int)))
produces a DecodeError with path = [Field("user"), Field("address"), Field("zip")] if as_int fails, vs. the raw form
d |> Dynamic.field("user") |> try |> Dynamic.field("address") |> try |> Dynamic.field("zip") |> try |> Dynamic.as_int()
which produces an empty-path error because try returns Err unchanged. Use
this when you want path-rich diagnostics; the raw form stays available when
you don’t.
Field-missing failures from the navigator itself pass through unchanged —
they already carry [Field(name)] from field’s own error, so the path is
not doubled.
Dynamic.at_index
Section titled “Dynamic.at_index”fn at_index<T>(d: Dynamic, i: Int, sub: (Dynamic) -> Result<T, DecodeError>): Result<T, DecodeError>
type function on Dynamic
List-index counterpart to at_field. Same path-accumulation behaviour:
prepends Index(i) to any error the sub-decoder returns; navigator failures
(out-of-bounds, non-list) pass through unchanged.
Dynamic.inspect
Section titled “Dynamic.inspect”fn inspect(d: Dynamic): String
impl Debug.inspect
enum PathSegment
Section titled “enum PathSegment”enum PathSegment { Field String Index Int }
One segment of a DecodeError’s path. Field for a dict-key navigation,
Index for a list-index navigation.
PathSegment.inspect
Section titled “PathSegment.inspect”fn inspect(value: PathSegment): String
impl Debug.inspect
PathSegment.to_string
Section titled “PathSegment.to_string”fn to_string(value: PathSegment): String
impl Display.to_string
struct DecodeError
Section titled “struct DecodeError”struct DecodeError { path: List<PathSegment> expected: String got: String }
Structured decode failure. path locates the failure site; one segment per
navigator that contributed to this error. Raw try chains short-circuit on
Err unchanged, so a chain like
d |> Dynamic.field("a") |> try |> Dynamic.field("b") |> try |> Dynamic.as_int()
produces an empty-path error if as_int fails — the outer navigators never
see the inner error to prepend their segment. Use at_field / at_index
when you want path-rich diagnostics; those combinators wrap a navigator +
sub-extractor and prepend the path segment on any error the sub-extractor
returns. expected and got name the type mismatch.
DecodeError.to_string
Section titled “DecodeError.to_string”fn to_string(e: DecodeError): String
impl Display.to_string
DecodeError.inspect
Section titled “DecodeError.inspect”fn inspect(value: DecodeError): String
impl Debug.inspect