diff options
author | sharno <sharnoby3@gmail.com> | 2020-10-26 22:01:48 -0400 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2020-10-27 15:14:56 +0100 |
commit | cbdd74a5e78a85be8d4d49a93b87e501e5b0aef5 (patch) | |
tree | 1837f4b1763ec8b712832ac13db5297b1d655e2b | |
parent | 5239830bc8bf6d8c1df566e7bfe995ff24d8514a (diff) | |
download | gleam_stdlib-cbdd74a5e78a85be8d4d49a93b87e501e5b0aef5.tar.gz gleam_stdlib-cbdd74a5e78a85be8d4d49a93b87e501e5b0aef5.zip |
Closes #115: Add dynamic.option
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | gleam | bin | 0 -> 19306232 bytes | |||
-rw-r--r-- | src/gleam/dynamic.gleam | 35 | ||||
-rw-r--r-- | test/gleam/dynamic_test.gleam | 18 |
4 files changed, 52 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1956083..b45b807 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - The `list` module gains the `each`, and `partition` functions. - The `int` and `float` modules gain the `negate` function. - The `result` module gains the `all` function. +- The `dynamic` module gains the `option` function. ## v0.11.0 - 2020-08-22 diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam index bf7963f..e4656c4 100644 --- a/src/gleam/dynamic.gleam +++ b/src/gleam/dynamic.gleam @@ -1,8 +1,9 @@ import gleam/bit_string.{BitString} as bit_string_mod import gleam/list as list_mod -import gleam/atom +import gleam/atom as atom_mod import gleam/map.{Map} import gleam/result +import gleam/option.{None, Option, Some} /// `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 @@ -102,7 +103,7 @@ pub external fn float(from: Dynamic) -> Result(Float, String) = /// > atom(from(123)) /// Error("Expected an Atom, got `123`") /// -pub external fn atom(from: Dynamic) -> Result(atom.Atom, String) = +pub external fn atom(from: Dynamic) -> Result(atom_mod.Atom, String) = "gleam_stdlib" "decode_atom" /// Check to see whether a Dynamic value is an bool, and return the bool if @@ -182,6 +183,36 @@ pub fn typed_list( |> result.then(list_mod.try_map(_, decoder_type)) } +/// Check to see if a Dynamic value is an Option of a particular type, and return +/// the Option 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. +/// +/// ## Examples +/// +/// > option(from("Hello"), string) +/// Ok(Some("Hello")) +/// +/// > option(from(atom.from_string("null")), string) +/// Ok(None) +/// +/// > option(from(123), string) +/// Error("Expected a bit_string, got an int") +/// +pub fn option( + from dynamic: Dynamic, + of decoder: Decoder(inner), +) -> Result(Option(inner), String) { + let Ok(null) = atom_mod.from_string("null") + case atom(dynamic), decoder(dynamic) { + Ok(atom), _ if atom == null -> Ok(None) + _, Ok(result) -> Ok(Some(result)) + _, Error(msg) -> Error(msg) + } +} + /// Check to see if a Dynamic value is a map with a specific field, and return /// the value of the field if it is. /// diff --git a/test/gleam/dynamic_test.gleam b/test/gleam/dynamic_test.gleam index 2b272d4..f4e78a0 100644 --- a/test/gleam/dynamic_test.gleam +++ b/test/gleam/dynamic_test.gleam @@ -5,6 +5,7 @@ import gleam/list import gleam/should import gleam/result import gleam/map +import gleam/option.{None, Some} pub fn bit_string_test() { "" @@ -220,6 +221,23 @@ pub fn typed_list_test() { |> should.be_error } +pub fn option_test() { + let Ok(null) = atom.from_string("null") + + 1 + |> dynamic.from + |> dynamic.option(dynamic.int) + |> should.equal(Ok(Some(1))) + null + |> dynamic.from + |> dynamic.option(dynamic.int) + |> should.equal(Ok(None)) + 1 + |> dynamic.from + |> dynamic.option(dynamic.string) + |> should.be_error +} + pub fn field_test() { let Ok(ok_atom) = atom.from_string("ok") let Ok(error_atom) = atom.from_string("error") |