diff options
author | Louis Pilfold <louis@lpil.uk> | 2022-01-09 17:03:43 +0000 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2022-01-09 17:03:43 +0000 |
commit | fba486a1398ba9e2bd066988d2ce088d2f328b8e (patch) | |
tree | 942451d53bf446c5fac4220bcc5029b90500b699 | |
parent | 71c40ec695b4cf08e917a3c70221739b9971f53d (diff) | |
download | gleam_stdlib-fba486a1398ba9e2bd066988d2ce088d2f328b8e.tar.gz gleam_stdlib-fba486a1398ba9e2bd066988d2ce088d2f328b8e.zip |
Curry element, decode2
-rw-r--r-- | CHANGELOG.md | 7 | ||||
-rw-r--r-- | src/gleam/dynamic.gleam | 92 | ||||
-rw-r--r-- | test/gleam/dynamic_test.gleam | 18 |
3 files changed, 86 insertions, 31 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index fda755b..0f8bc9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,11 @@ ## Unreleased -- The `result`, and `tuple*` functions have been removed from the `dynamic` - module. - The `dynamic` module gains the `dynamic` function. -- The `dynamic.list` function has been renamed to `dynamic.shallow_list`. +- The shallow `dynamic.list` function has been renamed to + `dynamic.shallow_list`. +- The shallow `result`, and `tuple*` functions have been removed from the + `dynamic` module. - The `dynamic.typed_list` function has been renamed to `dynamic.list`. - The `dynamic.typed_result` function has been renamed to `dynamic.result`. - The `dynamic.any` is now available on JavaScript. diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam index 744fdee..9281d8b 100644 --- a/src/gleam/dynamic.gleam +++ b/src/gleam/dynamic.gleam @@ -444,41 +444,42 @@ if javascript { /// ## Examples /// /// ```gleam -/// > element(from(#(1, 2)), 0) +/// > from(#(1, 2)) +/// > |> element(0, int) /// Ok(from(1)) +/// ``` /// -/// > element(from(#(1, 2)), 2) -/// Error([ -/// DecodeError(expected: "3 element tuple", found: "2 element tuple", path: [])]), -/// ]) -/// -/// > element(from(""), 2) +/// ```gleam +/// > from(#(1, 2)) +/// > |> element(2, int) /// Error([ -/// DecodeError(expected: "Tuple", found: "String", path: [])]), +/// DecodeError( +/// expected: "Tuple of at least 3 elements", +/// found: "Tuple of 2 elements", +/// path: [], +/// ), /// ]) /// ``` /// -pub fn element( - from data: Dynamic, - at index: Int, - of inner_type: Decoder(t), -) -> Result(t, DecodeErrors) { - try tuple = decode_tuple(data) - let size = tuple_size(tuple) - try data = case index >= 0 { - True -> - case index < size { - True -> tuple_get(tuple, index) - False -> at_least_decode_tuple_error(index + 1, data) - } - False -> - case int.absolute_value(index) <= size { - True -> tuple_get(tuple, size + index) - False -> at_least_decode_tuple_error(int.absolute_value(index), data) - } +pub fn element(at index: Int, of inner_type: Decoder(t)) -> Decoder(t) { + fn(data: Dynamic) { + try tuple = decode_tuple(data) + let size = tuple_size(tuple) + try data = case index >= 0 { + True -> + case index < size { + True -> tuple_get(tuple, index) + False -> at_least_decode_tuple_error(index + 1, data) + } + False -> + case int.absolute_value(index) <= size { + True -> tuple_get(tuple, size + index) + False -> at_least_decode_tuple_error(int.absolute_value(index), data) + } + } + inner_type(data) + |> map_errors(push_path(_, index)) } - inner_type(data) - |> map_errors(push_path(_, index)) } fn exact_decode_tuple_error(size: Int, data: Dynamic) -> Result(a, DecodeErrors) { @@ -877,3 +878,38 @@ pub fn any( } } } + +/// Decode 2 values from a `Dynamic` value. +/// +/// ## Examples +/// +/// ```gleam +/// > from(#(1, 2.0, "3")) +/// > |> decode2(MyRecord, element(0, int), element(1, float)) +/// Ok(MyRecord(1, 2.0)) +/// ``` +/// +/// ```gleam +/// > from(#("", "", "")) +/// > |> decode2(MyRecord, element(0, int), element(1, float)) +/// Error([ +/// DecodeError(expected: "Int", found: "String", path: ["0"]), +/// DecodeError(expected: "Float", found: "String", path: ["1"]), +/// ]) +/// ``` +/// +pub fn decode2( + constructor: fn(t1, t2) -> t, + decode1: Decoder(t1), + decode2: Decoder(t2), +) -> Decoder(t) { + fn(value) { + case decode1(value), decode2(value) { + Ok(a), Ok(b) -> Ok(constructor(a, b)) + a, b -> + tuple_errors(a, "0") + |> list.append(tuple_errors(b, "1")) + |> Error + } + } +} diff --git a/test/gleam/dynamic_test.gleam b/test/gleam/dynamic_test.gleam index 649a274..376d2a2 100644 --- a/test/gleam/dynamic_test.gleam +++ b/test/gleam/dynamic_test.gleam @@ -787,3 +787,21 @@ pub fn any_test() { |> decoder |> should.equal(Error([DecodeError("another type", "String", path: [])])) } + +type Two(a, b) { + Two(a, b) +} + +pub fn decode2_test() { + let decoder = + dynamic.decode2( + Two, + dynamic.element(0, dynamic.int), + dynamic.element(1, dynamic.float), + ) + + #(1, 2.0) + |> dynamic.from + |> decoder + |> should.equal(Ok(Two(1, 2.0))) +} |