diff options
author | Louis Pilfold <louis@lpil.uk> | 2020-07-07 12:06:07 +0100 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2020-07-07 12:06:07 +0100 |
commit | 28fdf1078ca67f224944bffebe46151ba4a9234a (patch) | |
tree | 1ce4df5b4827e96a89b5b575302dfbd30accdd32 | |
parent | 508fd5b979c597e35313e1fea970356d9fbc6c96 (diff) | |
download | gleam_stdlib-28fdf1078ca67f224944bffebe46151ba4a9234a.tar.gz gleam_stdlib-28fdf1078ca67f224944bffebe46151ba4a9234a.zip |
dynamic.any
-rw-r--r-- | CHANGELOG.md | 6 | ||||
-rw-r--r-- | src/gleam/dynamic.gleam | 36 | ||||
-rw-r--r-- | src/gleam/list.gleam | 2 | ||||
-rw-r--r-- | src/gleam/uri.gleam | 24 |
4 files changed, 47 insertions, 21 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1db3cd2..f09670c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,13 @@ # Changelog +## Unreleased + - Fix `uri.parse_query` to handle the case where query parameters are present without a value. +- The types for `list.find_map` have been relaxed. +- The `dynamic.typed_list` argument label has changed from `containing` to + `of`. +- The `dynamic` module gains the `any` function. ## v0.10.1 - 2020-07-01 diff --git a/src/gleam/dynamic.gleam b/src/gleam/dynamic.gleam index 648ad0a..efd8dd5 100644 --- a/src/gleam/dynamic.gleam +++ b/src/gleam/dynamic.gleam @@ -166,18 +166,18 @@ pub external fn list(from: Dynamic) -> Result(List(Dynamic), String) = /// /// ## Examples /// -/// > typed_list(from(["a", "b", "c"]), containing: string) +/// > typed_list(from(["a", "b", "c"]), of: string) /// Ok(["a", "b", "c"]) /// -/// > typed_list(from([1, 2, 3]), containing: string) +/// > typed_list(from([1, 2, 3]), of: string) /// Error("Expected an Int, got a binary") /// -/// > typed_list(from("ok"), containing: string) +/// > typed_list(from("ok"), of: string) /// Error("Expected a List, got a binary") /// pub fn typed_list( from dynamic: Dynamic, - containing decoder_type: fn(Dynamic) -> Result(inner, String), + of decoder_type: fn(Dynamic) -> Result(inner, String), ) -> Result(List(inner), String) { dynamic |> list @@ -289,3 +289,31 @@ pub fn typed_tuple2( /// pub external fn map(from: Dynamic) -> Result(Map(Dynamic, Dynamic), String) = "gleam_stdlib" "decode_map" + +/// Join multiple decoders into one. When run they will each be tried in turn +/// until one succeeds, or they all fail. +/// +/// ## Examples +/// +/// > import gleam/result +/// > let bool_or_string = any(_, of: [ +/// > string, +/// > fn(x) { result.map(bool(x), fn(_) { "a bool" }) } +/// > ]) +/// > bool_or_string(from("ok")) +/// Ok("ok") +/// +/// > bool_or_string(from(True)) +/// Ok("a bool") +/// +/// > bool_or_string(from(1)) +/// Error("Unexpected value") +/// +pub fn any( + from data: Dynamic, + of decoders: List(Decoder(t)), +) -> Result(t, String) { + decoders + |> list_mod.find_map(fn(decoder) { decoder(data) }) + |> result.map_error(fn(_) { "Unexpected value" }) +} diff --git a/src/gleam/list.gleam b/src/gleam/list.gleam index c7aee2f..b13575b 100644 --- a/src/gleam/list.gleam +++ b/src/gleam/list.gleam @@ -504,7 +504,7 @@ pub fn find( /// pub fn find_map( in haystack: List(a), - with fun: fn(a) -> Result(b, Nil), + with fun: fn(a) -> Result(b, c), ) -> Result(b, Nil) { case haystack { [] -> Error(Nil) diff --git a/src/gleam/uri.gleam b/src/gleam/uri.gleam index 1c2447b..cf18952 100644 --- a/src/gleam/uri.gleam +++ b/src/gleam/uri.gleam @@ -79,24 +79,16 @@ external fn erl_parse_query(String) -> Dynamic = /// The opposite operation is `uri.query_to_string`. /// pub fn parse_query(query: String) -> Result(List(tuple(String, String)), Nil) { + let bool_value = fn(x) { result.map(dynamic.bool(x), fn(_) { "" }) } + let query_param = dynamic.typed_tuple2( + _, + dynamic.string, + dynamic.any(_, of: [dynamic.string, bool_value]), + ) + query |> erl_parse_query - |> dynamic.typed_list( - dynamic.typed_tuple2( - _, - dynamic.string, - fn(raw) { - case dynamic.string(raw) { - Ok(value) -> Ok(value) - Error(_reason) -> case dynamic.bool(raw) { - Ok(True) -> Ok("") - // Note this error message will be niled at the end of this function. - _ -> Error("expected a boolean or string, got neither") - } - } - }, - ), - ) + |> dynamic.typed_list(of: query_param) |> result.nil_error } |