aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsharno <sharnoby3@gmail.com>2020-10-26 22:01:48 -0400
committerLouis Pilfold <louis@lpil.uk>2020-10-27 15:14:56 +0100
commitcbdd74a5e78a85be8d4d49a93b87e501e5b0aef5 (patch)
tree1837f4b1763ec8b712832ac13db5297b1d655e2b
parent5239830bc8bf6d8c1df566e7bfe995ff24d8514a (diff)
downloadgleam_stdlib-cbdd74a5e78a85be8d4d49a93b87e501e5b0aef5.tar.gz
gleam_stdlib-cbdd74a5e78a85be8d4d49a93b87e501e5b0aef5.zip
Closes #115: Add dynamic.option
-rw-r--r--CHANGELOG.md1
-rw-r--r--gleambin0 -> 19306232 bytes
-rw-r--r--src/gleam/dynamic.gleam35
-rw-r--r--test/gleam/dynamic_test.gleam18
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/gleam b/gleam
new file mode 100644
index 0000000..7f13854
--- /dev/null
+++ b/gleam
Binary files differ
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")