aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Pilfold <louis@lpil.uk>2021-09-10 20:32:50 +0100
committerLouis Pilfold <louis@lpil.uk>2021-09-10 20:32:50 +0100
commita6b75f614c97f7cf2bede89b5769bfcd13c31571 (patch)
treec6db67376e64f69759051488134f7c8dc8267d65
parent72889a32caa561ffe083a7c921f856c23c0ee5f6 (diff)
downloadgleam_stdlib-a6b75f614c97f7cf2bede89b5769bfcd13c31571.tar.gz
gleam_stdlib-a6b75f614c97f7cf2bede89b5769bfcd13c31571.zip
Optional
-rw-r--r--src/gleam/dynamic.gleam78
-rw-r--r--src/gleam_stdlib.js12
-rw-r--r--test/gleam/dynamic_test.gleam40
3 files changed, 78 insertions, 52 deletions
diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam
index 726fbeb..2175461 100644
--- a/src/gleam/dynamic.gleam
+++ b/src/gleam/dynamic.gleam
@@ -6,10 +6,7 @@ import gleam/option
import gleam/result
import gleam/string_builder
import gleam/map.{Map}
-
-if erlang {
- import gleam/option.{Option}
-}
+import gleam/option.{Option}
/// `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
@@ -339,36 +336,53 @@ pub fn typed_list(
|> result.then(list.try_map(_, decoder_type))
}
+/// 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 optional(
+ from value: Dynamic,
+ of decode: Decoder(inner),
+) -> Result(Option(inner), DecodeError) {
+ decode_optional(value, decode)
+}
+
if erlang {
- /// 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 external fn optional(
- from: Dynamic,
- of: Decoder(inner),
- ) -> Result(Option(inner), DecodeError) =
- "gleam_stdlib" "decode_optional"
+ external fn decode_optional(
+ Dynamic,
+ Decoder(Option(a)),
+ ) -> Result(a, DecodeError) =
+ "gleam_stdlib" "decode_optionl"
+}
+if javascript {
+ external fn decode_optional(
+ Dynamic,
+ Decoder(a),
+ ) -> Result(Option(a), DecodeError) =
+ "../gleam_stdlib.js" "decode_option"
+}
+
+if erlang {
/// Checks 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/src/gleam_stdlib.js b/src/gleam_stdlib.js
index 4c52daf..37f071a 100644
--- a/src/gleam_stdlib.js
+++ b/src/gleam_stdlib.js
@@ -540,3 +540,15 @@ export function decode_result(data) {
export function decode_map(data) {
return data instanceof Map ? new Ok(data) : decoder_error("Map", data);
}
+
+export function decode_option(data, decoder) {
+ if (data === null || data === undefined || data instanceof None)
+ return new Ok(new None());
+ if (data instanceof Some) data = data[0];
+ let result = decoder(data);
+ if (result.isOk()) {
+ return new Ok(new Some(result[0]));
+ } else {
+ return result;
+ }
+}
diff --git a/test/gleam/dynamic_test.gleam b/test/gleam/dynamic_test.gleam
index 2fb4a2a..c062d91 100644
--- a/test/gleam/dynamic_test.gleam
+++ b/test/gleam/dynamic_test.gleam
@@ -2,11 +2,11 @@ import gleam/should
import gleam/dynamic.{DecodeError}
import gleam/bit_string
import gleam/map
+import gleam/option.{None, Some}
if erlang {
import gleam/list
import gleam/result
- import gleam/option.{None, Some}
}
pub fn bit_string_test() {
@@ -202,29 +202,29 @@ pub fn typed_list_test() {
|> should.be_error
}
-if erlang {
- pub fn optional_test() {
- 1
- |> dynamic.from
- |> dynamic.optional(dynamic.int)
- |> should.equal(Ok(Some(1)))
+pub fn optional_test() {
+ 1
+ |> dynamic.from
+ |> dynamic.optional(dynamic.int)
+ |> should.equal(Ok(Some(1)))
- option.None
- |> dynamic.from
- |> dynamic.optional(dynamic.int)
- |> should.equal(Ok(None))
+ option.None
+ |> dynamic.from
+ |> dynamic.optional(dynamic.int)
+ |> should.equal(Ok(None))
- Nil
- |> dynamic.from
- |> dynamic.optional(dynamic.int)
- |> should.equal(Ok(None))
+ Nil
+ |> dynamic.from
+ |> dynamic.optional(dynamic.int)
+ |> should.equal(Ok(None))
- 1
- |> dynamic.from
- |> dynamic.optional(dynamic.string)
- |> should.be_error
- }
+ 1
+ |> dynamic.from
+ |> dynamic.optional(dynamic.string)
+ |> should.be_error
+}
+if erlang {
pub fn field_test() {
map.new()
|> map.insert("ok", 1)