aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Pilfold <louis@lpil.uk>2020-05-19 18:55:06 +0100
committerLouis Pilfold <louis@lpil.uk>2020-05-19 19:22:49 +0100
commit5ca885bd114635244d25f2f91c35bda448e6a635 (patch)
tree3139a84b322575e8044e392d2df6d88ba95840f3
parentcbf07061be7524aa049864b6dec49715e641499a (diff)
downloadgleam_stdlib-5ca885bd114635244d25f2f91c35bda448e6a635.tar.gz
gleam_stdlib-5ca885bd114635244d25f2f91c35bda448e6a635.zip
list.filter_map
-rw-r--r--CHANGELOG.md1
-rw-r--r--src/gleam/gleam_uri_native.erl20
-rw-r--r--src/gleam/list.gleam32
-rw-r--r--src/gleam/uri.gleam36
-rw-r--r--test/gleam/list_test.gleam10
5 files changed, 78 insertions, 21 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7926881..2ed6646 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@
- `uri` module created with `parse`, `parse_query`, `path_segments`,
`query_to_string` and `to_string`.
- The `dynamic` module gains the `tuple2`, and `tuple2_of` functions.
+- The `list` module gains the `filter_map` function.
## v0.8.0 - 2020-04-28
diff --git a/src/gleam/gleam_uri_native.erl b/src/gleam/gleam_uri_native.erl
index 5d225cb..dafd406 100644
--- a/src/gleam/gleam_uri_native.erl
+++ b/src/gleam/gleam_uri_native.erl
@@ -1,5 +1,5 @@
-module (gleam_uri_native).
--export ([parse/1, to_string/1, parse_query/1]).
+-export ([parse/1]).
find_key(Key, Map) ->
case maps:find(Key, Map) of
@@ -25,21 +25,3 @@ parse(String) ->
find_key(fragment, Map)
}}
end.
-
-to_string({uri, MaybeScheme, MaybeUserinfo, MaybeHost, MaybePort, Path, MaybeQuery, MaybeFragment}) ->
- Components = [{scheme, MaybeScheme}, {userinfo, MaybeUserinfo}, {host, MaybeHost}, {port, MaybePort}, {path, {ok, Path}}, {query, MaybeQuery}, {fragment, MaybeFragment}],
- Map = maps:from_list([{K, V} || {K, {ok, V}} <- Components]),
- case uri_string:recompose(Map) of
- String when is_binary(String) ->
- String;
- % Return value when empty
- [] -> <<"">>
- end.
-
-parse_query(String) ->
- case uri_string:dissect_query(String) of
- {error, _Reason, _Term} ->
- {error, nil};
- Parts ->
- {ok, Parts}
- end.
diff --git a/src/gleam/list.gleam b/src/gleam/list.gleam
index a0098a1..4e10c15 100644
--- a/src/gleam/list.gleam
+++ b/src/gleam/list.gleam
@@ -196,6 +196,38 @@ pub fn filter(list: List(a), for predicate: fn(a) -> Bool) -> List(a) {
do_filter(list, predicate, [])
}
+fn do_filter_map(
+ list: List(a),
+ fun: fn(a) -> Result(b, e),
+ acc: List(b),
+) -> List(b) {
+ case list {
+ [] -> reverse(acc)
+ [x, ..xs] -> {
+ let new_acc = case fun(x) {
+ Ok(x) -> [x, ..acc]
+ Error(_) -> acc
+ }
+ do_filter_map(xs, fun, new_acc)
+ }
+ }
+}
+
+/// Returns a new list containing only the elements from the first list for
+/// which the given functions returns `True`.
+///
+/// ## Examples
+///
+/// > filter_map([2, 4, 6, 1], Error)
+/// []
+///
+/// > filter_map([2, 4, 6, 1], fn(x) { Ok(x + 1) })
+/// [3, 4, 6, 2]
+///
+pub fn filter_map(list: List(a), with fun: fn(a) -> Result(b, e)) -> List(b) {
+ do_filter_map(list, fun, [])
+}
+
fn do_map(list: List(a), fun: fn(a) -> b, acc: List(b)) -> List(b) {
case list {
[] -> reverse(acc)
diff --git a/src/gleam/uri.gleam b/src/gleam/uri.gleam
index 8536d98..a62cf3c 100644
--- a/src/gleam/uri.gleam
+++ b/src/gleam/uri.gleam
@@ -11,6 +11,7 @@ import gleam/list
import gleam/result.{Option}
import gleam/string
import gleam/dynamic.{Dynamic}
+import gleam/map.{Map}
/// Type representing holding the parsed components of an URI.
/// All components of a URI are optional, except the path.
@@ -100,9 +101,40 @@ pub fn path_segments(path) {
do_path_segments(string.split(path, "/"), [])
}
+type UriKey {
+ Scheme
+ Userinfo
+ Host
+ Port
+ Path
+ Query
+ Fragment
+}
+
+external fn erl_to_string(Map(UriKey, Dynamic)) -> Dynamic =
+ "uri_string" "recompose"
+
/// Encode a `Uri` value as a URI string.
///
/// The opposite operation is `uri.parse`.
///
-pub external fn to_string(Uri) -> String =
- "gleam_uri_native" "to_string"
+pub fn to_string(uri: Uri) -> String {
+ let field = fn(key: UriKey, value: Option(anything)) {
+ result.map(value, fn(value) { tuple(key, dynamic.from(value)) })
+ }
+
+ [
+ field(Scheme, uri.scheme),
+ field(Userinfo, uri.userinfo),
+ field(Host, uri.host),
+ field(Port, uri.port),
+ field(Path, Ok(uri.path)),
+ field(Query, uri.query),
+ field(Fragment, uri.fragment),
+ ]
+ |> list.filter_map(fn(x) { x })
+ |> map.from_list
+ |> erl_to_string
+ |> dynamic.string
+ |> result.unwrap("")
+}
diff --git a/test/gleam/list_test.gleam b/test/gleam/list_test.gleam
index 1be4e43..4576d7f 100644
--- a/test/gleam/list_test.gleam
+++ b/test/gleam/list_test.gleam
@@ -79,6 +79,16 @@ pub fn filter_test() {
|> should.equal([0, 3])
}
+pub fn filter_map_test() {
+ [2, 4, 6, 1]
+ |> list.filter_map(fn(x) { Ok(x + 1) })
+ |> should.equal([3, 5, 7, 2])
+
+ [2, 4, 6, 1]
+ |> list.filter_map(Error)
+ |> should.equal([])
+}
+
pub fn map_test() {
[]
|> list.map(fn(x) { x * 2 })