gleam/dynamic

Types

Error returned when unexpected data is encountered

pub type DecodeError {
  DecodeError(expected: String, found: String)
}

Constructors

  • DecodeError(expected: String, found: String)
pub type Decoder(t) =
  fn(Dynamic) -> Result(t, DecodeError)

Dynamic data is data that we don’t know the type of yet. We likely get data like this from interop with Erlang, or from IO with the outside world.

pub external type Dynamic

Functions

pub fn any(
  from data: Dynamic,
  of decoders: List(fn(Dynamic) -> Result(a, DecodeError)),
) -> Result(a, DecodeError)

Joins multiple decoders into one. When run they will each be tried in turn until one succeeds, or they all fail.

Examples

> import gleam/result
> let bool_or_string = any(_, of: [
>   string,
>   fn(x) { result.map(bool(x), fn(_) { "a bool" }) }
> ])
> bool_or_string(from("ok"))
Ok("ok")

> bool_or_string(from(True))
Ok("a bool")

> bool_or_string(from(1))
Error(DecodeError(expected: "unknown", found: "unknown"))
pub fn bit_string(
  from data: Dynamic,
) -> Result(BitString, DecodeError)

Checks to see whether a Dynamic value is a bit_string, and return the bit_string if it is.

Examples

> bit_string(from("Hello")) == bit_string.from_string("Hello")
True

> bit_string(from(123))
Error(DecodeError(expected: "BitString", found: "Int"))
pub fn bool(from data: Dynamic) -> Result(Bool, DecodeError)

Checks to see whether a Dynamic value is an bool, and return the bool if it is.

Examples

> bool(from(True))
Ok(True)

> bool(from(123))
Error(DecodeError(expected: "bool", found: "Int"))
pub fn classify(data: Dynamic) -> String

Return a string indicating the type of the dynamic value.

> classify(from("Hello"))
"String"
pub fn element(
  from data: Dynamic,
  get index: Int,
) -> Result(Dynamic, DecodeError)

Checks to see if the Dynamic value is a tuple large enough to have a certain index, and return the value of that index if it is.

Examples

> element(from(#(1, 2)), 0)
Ok(from(1))

> element(from(#(1, 2)), 2)
Error(DecodeError(expected: "3 element tuple", found: "2 element tuple"))

> element(from(""), 2)
Error(DecodeError(expected: "Tuple", found: "String"))
pub fn field(
  from value: Dynamic,
  named name: a,
) -> Result(Dynamic, DecodeError)

Checks to see if a Dynamic value is a map with a specific field, and return the value of the field if it is.

This will not succeed on a record.

Examples

> import gleam/map
> field(from(map.new("Hello", "World")), "Hello")
Ok(Dynamic)

> field(from(123), "Hello")
Error(DecodeError(expected: "Map", found: "Int"))
pub fn float(from data: Dynamic) -> Result(Float, DecodeError)

Checks to see whether a Dynamic value is an float, and return the float if it is.

Examples

> float(from(2.0))
Ok(2.0)

> float(from(123))
Error(DecodeError(expected: "Float", found: "Int"))
pub fn from(a: a) -> Dynamic

Converts any Gleam data into Dynamic data.

pub fn int(from data: Dynamic) -> Result(Int, DecodeError)

Checks to see whether a Dynamic value is an int, and return the int if it is.

Examples

> int(from(123))
Ok(123)

> int(from("Hello"))
Error(DecodeError(expected: "Int", found: "String"))
pub fn list(
  from value: Dynamic,
) -> Result(List(Dynamic), DecodeError)

Checks to see whether a Dynamic value is a list, and return the list if it is.

If you wish to decode all the elements in the list use the typed_list instead.

Examples

> list(from(["a", "b", "c"]))
Ok([from("a"), from("b"), from("c")])

> list(1)
Error(DecodeError(expected: "Int", found: "Int"))
pub fn map(
  from value: Dynamic,
) -> Result(Map(Dynamic, Dynamic), DecodeError)

Checks to see if the Dynamic value is map.

Examples

> import gleam/map
> map(from(map.new()))
Ok(map.new())

> map(from(1))
Error(DecodeError(expected: "Map", found: "Int"))

> map(from(""))
Error(DecodeError(expected: "Map", found: "String"))
pub fn optional(
  from value: Dynamic,
  of decode: fn(Dynamic) -> Result(a, DecodeError),
) -> Result(Option(a), DecodeError)

Checks to see if a Dynamic value is a nullable version of a particular type, and return the Option if it is.

Examples

> option(from("Hello"), string)
Ok(Some("Hello"))

> option(from("Hello"), string)
Ok(Some("Hello"))

> option(from(atom.from_string("null")), string)
Ok(None)

> option(from(atom.from_string("nil")), string)
Ok(None)

> option(from(atom.from_string("undefined")), string)
Ok(None)

> option(from(123), string)
Error(DecodeError(expected: "BitString", found: "Int"))
pub fn result(
  from value: Dynamic,
) -> Result(Result(Dynamic, Dynamic), DecodeError)

Checks to see whether a Dynamic value is a result, and return the result if it is.

Examples

> result(from(Ok(1)))
Ok(Ok(from(1)))

> result(from(Error("boom")))
Ok(Error(from("boom")))

> result(from(123))
Error(DecodeError(expected: "2 element tuple", found: "Int"))
pub fn string(from data: Dynamic) -> Result(String, DecodeError)

Checks to see whether a Dynamic value is a string, and return the string if it is.

Examples

> string(from("Hello"))
Ok("Hello")

> string(from(123))
Error(DecodeError(expected: "String", found: "Int"))
pub fn tuple2(
  from value: Dynamic,
) -> Result(#(Dynamic, Dynamic), DecodeError)

Checks to see if the Dynamic value is a 2 element tuple.

If you do not wish to decode all the elements in the tuple use the typed_tuple2 function instead.

Examples

> tuple2(from(#(1, 2)))
Ok(#(from(1), from(2)))

> tuple2(from(#(1, 2, 3)))
Error(DecodeError(expected: "2 element tuple", found: "3 element tuple"))

> tuple2(from(""))
Error(DecodeError(expected: "2 element tuple", found: "String"))
pub fn tuple3(
  from value: Dynamic,
) -> Result(#(Dynamic, Dynamic, Dynamic), DecodeError)

Checks to see if the Dynamic value is a 3 element tuple.

If you do not wish to decode all the elements in the tuple use the typed_tuple3 function instead.

Examples

> tuple3(from(#(1, 2, 3)))
Ok(#(from(1), from(2), from(3)))

> tuple3(from(#(1, 2)))
Error(DecodeError(expected: "3 element tuple", found: "3 element tuple"))

> tuple3(from(""))
Error(DecodeError(expected: "3 element tuple", found: "String"))
pub fn tuple4(
  from value: Dynamic,
) -> Result(#(Dynamic, Dynamic, Dynamic, Dynamic), DecodeError)

Checks to see if the Dynamic value is a 4 element tuple.

If you do not wish to decode all the elements in the tuple use the typed_tuple4 function instead.

Examples

> tuple4(from(#(1, 2, 3, 4)))
Ok(#(from(1), from(2), from(3), from(4)))

> tuple4(from(#(1, 2)))
Error(DecodeError(expected: "4 element tuple", found: "2 element tuple"))

> tuple4(from(""))
Error(DecodeError(expected: "4 element tuple", found: "String"))
pub fn tuple5(
  from value: Dynamic,
) -> Result(
  #(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic),
  DecodeError,
)

Checks to see if the Dynamic value is a 5 element tuple.

If you do not wish to decode all the elements in the tuple use the typed_tuple5 function instead.

Examples

> tuple5(from(#(1, 2, 3, 4, 5)))
Ok(#(from(1), from(2), from(3), from(4), from(5)))

> tuple5(from(#(1, 2)))
Error(DecodeError(expected: "5 element tuple", found: "2 element tuple"))

> tuple5(from(""))
Error(DecodeError(expected: "5 element tuple", found: "String"))
pub fn tuple6(
  from value: Dynamic,
) -> Result(
  #(Dynamic, Dynamic, Dynamic, Dynamic, Dynamic, Dynamic),
  DecodeError,
)

Checks to see if the Dynamic value is a 6 element tuple.

If you do not wish to decode all the elements in the tuple use the typed_tuple6 function instead.

Examples

> tuple6(from(#(1, 2, 3, 4, 5, 6)))
Ok(#(from(1), from(2), from(3), from(4), from(5), from(6)))

> tuple6(from(#(1, 2)))
Error(DecodeError(expected: "6 element tuple", found: "2 element tuple"))

> tuple6(from(""))
Error(DecodeError(expected: "6 element tuple", found: "String"))
pub fn typed_list(
  from dynamic: Dynamic,
  of decoder_type: fn(Dynamic) -> Result(a, DecodeError),
) -> Result(List(a), DecodeError)

Checks to see whether a Dynamic value is a list of a particular type, and return the list if it is.

The second argument is a decoder function used to decode the elements of the list. The list is only decoded if all elements in the list can be successfully decoded using this function.

If you do not wish to decode all the elements in the list use the list function instead.

Examples

> typed_list(from(["a", "b", "c"]), of: string)
Ok(["a", "b", "c"])

> typed_list(from([1, 2, 3]), of: string)
Error(DecodeError(expected: "String", found: "Int"))

> typed_list(from("ok"), of: string)
Error(DecodeError(expected: "List", found: "String"))
pub fn typed_result(
  of dynamic: Dynamic,
  ok decode_ok: fn(Dynamic) -> Result(a, DecodeError),
  error decode_error: fn(Dynamic) -> Result(b, DecodeError),
) -> Result(Result(a, b), DecodeError)

Checks to see whether a Dynamic value is a result of a particular type, and return the result if it is

The ok and error arguments are decoders for decoding the Ok and Error values of the result.

Examples

> typed_result(of: from(Ok(1)), ok: int, error: string)
Ok(Ok(1))

> typed_result(of: from(Error("boom")), ok: int, error: string)
Ok(Error("boom"))

> typed_result(of: from(123), ok: int, error: string)
Error(DecodeError(expected: "2 element tuple", found: "Int"))
pub fn typed_tuple2(
  from tup: Dynamic,
  first decode_first: fn(Dynamic) -> Result(a, DecodeError),
  second decode_second: fn(Dynamic) -> Result(b, DecodeError),
) -> Result(#(a, b), DecodeError)

Checks to see if the Dynamic value is a 2 element tuple containing two specifically typed elements.

If you wish to decode all the elements in the list use the typed_tuple2 instead.

Examples

> typed_tuple2(from(#(1, 2)), int, int)
Ok(#(1, 2))

> typed_tuple2(from(#(1, 2.0)), int, float)
Ok(#(1, 2.0))

> typed_tuple2(from(#(1, 2, 3)), int, float)
Error(DecodeError(expected: "2 element tuple", found: "3 element tuple"))

> typed_tuple2(from(""), int, float)
Error(DecodeError(expected: "2 element tuple", found: "String"))
pub fn typed_tuple3(
  from tup: Dynamic,
  first decode_first: fn(Dynamic) -> Result(a, DecodeError),
  second decode_second: fn(Dynamic) -> Result(b, DecodeError),
  third decode_third: fn(Dynamic) -> Result(c, DecodeError),
) -> Result(#(a, b, c), DecodeError)

Checks to see if the Dynamic value is a 3 element tuple containing two specifically typed elements.

If you wish to decode all the elements in the list use the typed_tuple3 instead.

Examples

> typed_tuple3(from(#(1, 2, 3)), int, int, int)
Ok(#(1, 2, 3))

> typed_tuple3(from(#(1, 2.0, "3")), int, float, string)
Ok(#(1, 2.0, "3"))

> typed_tuple3(from(#(1, 2)), int, float, string)
Error(DecodeError(expected: "3 element tuple", found: "2 element tuple"))

> typed_tuple3(from(""), int, float, string)
Error(DecodeError(expected: "3 element tuple", found: "String"))
pub fn typed_tuple4(
  from tup: Dynamic,
  first decode_first: fn(Dynamic) -> Result(a, DecodeError),
  second decode_second: fn(Dynamic) -> Result(b, DecodeError),
  third decode_third: fn(Dynamic) -> Result(c, DecodeError),
  fourth decode_fourth: fn(Dynamic) -> Result(d, DecodeError),
) -> Result(#(a, b, c, d), DecodeError)

Checks to see if the Dynamic value is a 4 element tuple containing two specifically typed elements.

If you wish to decode all the elements in the list use the typed_tuple4 instead.

Examples

> typed_tuple4(from(#(1, 2, 3, 4)), int, int, int, int)
Ok(#(1, 2, 3, 4))

> typed_tuple4(from(#(1, 2.0, "3", 4)), int, float, string, int)
Ok(#(1, 2.0, "3", 4))

> typed_tuple4(from(#(1, 2)), int, float, string, int)
Error("Expected a 4 element tuple, found a 2 element tuple")
Error(DecodeError(expected: "4 element tuple", found: "2 element tuple"))

> typed_tuple4(from(""), int, float, string, int)
Error(DecodeError(expected: "4 element tuple", found: "String"))
pub fn typed_tuple5(
  from tup: Dynamic,
  first decode_first: fn(Dynamic) -> Result(a, DecodeError),
  second decode_second: fn(Dynamic) -> Result(b, DecodeError),
  third decode_third: fn(Dynamic) -> Result(c, DecodeError),
  fourth decode_fourth: fn(Dynamic) -> Result(d, DecodeError),
  fifth decode_fifth: fn(Dynamic) -> Result(e, DecodeError),
) -> Result(#(a, b, c, d, e), DecodeError)

Checks to see if the Dynamic value is a 5 element tuple containing two specifically typed elements.

If you wish to decode all the elements in the list use the typed_tuple5 instead.

Examples

> typed_tuple5(from(#(1, 2, 3, 4, 5)), int, int, int, int, int)
Ok(#(1, 2, 3, 4, 5))

> typed_tuple5(from(#(1, 2.0, "3", 4, 5)), int, float, string, int, int)
Ok(#(1, 2.0, "3", 4, 5))

> typed_tuple5(from(#(1, 2)), int, float, string, int, int)
Error(DecodeError(expected: "5 element tuple", found: "2 element tuple"))

> typed_tuple5(from(""), int, float, string, int, int)
Error(DecodeError(expected: "5 element tuple", found: "String"))
pub fn typed_tuple6(
  from tup: Dynamic,
  first decode_first: fn(Dynamic) -> Result(a, DecodeError),
  second decode_second: fn(Dynamic) -> Result(b, DecodeError),
  third decode_third: fn(Dynamic) -> Result(c, DecodeError),
  fourth decode_fourth: fn(Dynamic) -> Result(d, DecodeError),
  fifth decode_fifth: fn(Dynamic) -> Result(e, DecodeError),
  sixth decode_sixth: fn(Dynamic) -> Result(f, DecodeError),
) -> Result(#(a, b, c, d, e, f), DecodeError)

Checks to see if the Dynamic value is a 6 element tuple containing two specifically typed elements.

If you wish to decode all the elements in the list use the typed_tuple6 instead.

Examples

> typed_tuple6(from(#(1, 2, 3, 4, 5, 6)), int, int, int, int, int, int)
Ok(#(1, 2, 3, 4, 5, 6))

> typed_tuple6(from(#(1, 2.0, "3", 4, 5, 6)), int, float, string, int, int)
Ok(#(1, 2.0, "3", 4, 5, 6))

> typed_tuple6(from(#(1, 2)), int, float, string, int, int, int)
Error(DecodeError(expected: "6 element tuple", found: "2 element tuple"))

> typed_tuple6(from(""), int, float, string, int, int, int)
Error(DecodeError(expected: "6 element tuple", found: "String"))
pub fn unsafe_coerce(a: Dynamic) -> a

Unsafely casts a Dynamic value into any other type.

This is an escape hatch for the type system that may be useful when wrapping native Erlang APIs. It is to be used as a last measure only!

If you can avoid using this function, do!