aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Pilfold <louis@lpil.uk>2022-01-09 17:03:43 +0000
committerLouis Pilfold <louis@lpil.uk>2022-01-09 17:03:43 +0000
commitfba486a1398ba9e2bd066988d2ce088d2f328b8e (patch)
tree942451d53bf446c5fac4220bcc5029b90500b699
parent71c40ec695b4cf08e917a3c70221739b9971f53d (diff)
downloadgleam_stdlib-fba486a1398ba9e2bd066988d2ce088d2f328b8e.tar.gz
gleam_stdlib-fba486a1398ba9e2bd066988d2ce088d2f328b8e.zip
Curry element, decode2
-rw-r--r--CHANGELOG.md7
-rw-r--r--src/gleam/dynamic.gleam92
-rw-r--r--test/gleam/dynamic_test.gleam18
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)))
+}