From 0579308bf0559635e3742e7fa634648182d916c5 Mon Sep 17 00:00:00 2001 From: Louis Pilfold Date: Sun, 15 Sep 2019 21:05:05 +0100 Subject: Remove maps from stdlib --- CHANGELOG.md | 1 + gen/src/gleam@map.erl | 89 ++++++++++++++ gen/src/gleam@map_dict.erl | 89 -------------- gen/test/gleam@any_test.erl | 21 +++- gen/test/gleam@map_dict_test.erl | 157 ------------------------ gen/test/gleam@map_test.erl | 150 +++++++++++++++++++++++ src/gleam/map.gleam | 100 +++++++++++++++ src/gleam/map_dict.gleam | 100 --------------- test/gleam/any_test.gleam | 11 +- test/gleam/map_dict_test.gleam | 254 --------------------------------------- test/gleam/map_test.gleam | 254 +++++++++++++++++++++++++++++++++++++++ 11 files changed, 620 insertions(+), 606 deletions(-) create mode 100644 gen/src/gleam@map.erl delete mode 100644 gen/src/gleam@map_dict.erl delete mode 100644 gen/test/gleam@map_dict_test.erl create mode 100644 gen/test/gleam@map_test.erl create mode 100644 src/gleam/map.gleam delete mode 100644 src/gleam/map_dict.gleam delete mode 100644 test/gleam/map_dict_test.gleam create mode 100644 test/gleam/map_test.gleam diff --git a/CHANGELOG.md b/CHANGELOG.md index 9359814..01d80c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased - Syntax has been updated for Gleam v0.4. +- The `map_dict` module has been renamed to `map`. - `list:sort` now requires a compare function as comparison operators now only work on Ints. - `list:sort`'s performance has been slightly optimised. diff --git a/gen/src/gleam@map.erl b/gen/src/gleam@map.erl new file mode 100644 index 0000000..e3a2e35 --- /dev/null +++ b/gen/src/gleam@map.erl @@ -0,0 +1,89 @@ +-module(gleam@map). +-compile(no_auto_import). + +-export([size/1, to_list/1, from_list/1, has_key/2, new/0, fetch/2, put/3, map_values/2, keys/1, values/1, filter/2, take/2, merge/2, delete/2, drop/2, update/3, fold/3]). + +size(A) -> + maps:size(A). + +to_list(A) -> + maps:to_list(A). + +from_list(A) -> + maps:from_list(A). + +is_key(A, B) -> + maps:is_key(A, B). + +has_key(Map, Key) -> + is_key(Key, Map). + +new() -> + maps:new(). + +fetch(A, B) -> + gleam__stdlib:map_fetch(A, B). + +erl_put(A, B, C) -> + maps:put(A, B, C). + +put(Map, Key, Value) -> + erl_put(Key, Value, Map). + +erl_map_values(A, B) -> + maps:map(A, B). + +map_values(Map, Fun) -> + erl_map_values(Fun, Map). + +keys(A) -> + maps:keys(A). + +values(A) -> + maps:values(A). + +erl_filter(A, B) -> + maps:filter(A, B). + +filter(Map, Fun) -> + erl_filter(Fun, Map). + +erl_take(A, B) -> + maps:with(A, B). + +take(Map, Keys) -> + erl_take(Keys, Map). + +merge(A, B) -> + maps:merge(A, B). + +erl_delete(A, B) -> + maps:remove(A, B). + +delete(Map, Key) -> + erl_delete(Key, Map). + +drop(Map, Keys) -> + gleam@list:fold(Keys, Map, fun(Key, Acc) -> delete(Acc, Key) end). + +update(Dict, Key, F) -> + case fetch(Dict, Key) of + {ok, Value} -> + put(Dict, Key, F({ok, Value})); + + {error, _} -> + put(Dict, Key, F({error, not_found})) + end. + +do_fold(List, Acc, F) -> + case List of + [] -> + Acc; + + [{K, V} | Tail] -> + do_fold(Tail, F(K, V, Acc), F) + end. + +fold(Dict, Acc, F) -> + Kvs = to_list(Dict), + do_fold(Kvs, Acc, F). diff --git a/gen/src/gleam@map_dict.erl b/gen/src/gleam@map_dict.erl deleted file mode 100644 index 77eaf79..0000000 --- a/gen/src/gleam@map_dict.erl +++ /dev/null @@ -1,89 +0,0 @@ --module(gleam@map_dict). --compile(no_auto_import). - --export([size/1, to_list/1, from_list/1, has_key/2, new/0, fetch/2, put/3, map_values/2, keys/1, values/1, filter/2, take/2, merge/2, delete/2, drop/2, update/3, fold/3]). - -size(A) -> - maps:size(A). - -to_list(A) -> - maps:to_list(A). - -from_list(A) -> - maps:from_list(A). - -is_key(A, B) -> - maps:is_key(A, B). - -has_key(Map, Key) -> - is_key(Key, Map). - -new() -> - maps:new(). - -fetch(A, B) -> - gleam__stdlib:map_fetch(A, B). - -erl_put(A, B, C) -> - maps:put(A, B, C). - -put(Map, Key, Value) -> - erl_put(Key, Value, Map). - -erl_map_values(A, B) -> - maps:map(A, B). - -map_values(Map, Fun) -> - erl_map_values(Fun, Map). - -keys(A) -> - maps:keys(A). - -values(A) -> - maps:values(A). - -erl_filter(A, B) -> - maps:filter(A, B). - -filter(Map, Fun) -> - erl_filter(Fun, Map). - -erl_take(A, B) -> - maps:with(A, B). - -take(Map, Keys) -> - erl_take(Keys, Map). - -merge(A, B) -> - maps:merge(A, B). - -erl_delete(A, B) -> - maps:remove(A, B). - -delete(Map, Key) -> - erl_delete(Key, Map). - -drop(Map, Keys) -> - gleam@list:fold(Keys, Map, fun(Key, Acc) -> delete(Acc, Key) end). - -update(Dict, Key, F) -> - case fetch(Dict, Key) of - {ok, Value} -> - put(Dict, Key, F({ok, Value})); - - {error, _} -> - put(Dict, Key, F({error, not_found})) - end. - -do_fold(List, Acc, F) -> - case List of - [] -> - Acc; - - [{K, V} | Tail] -> - do_fold(Tail, F(K, V, Acc), F) - end. - -fold(Dict, Acc, F) -> - Kvs = to_list(Dict), - do_fold(Kvs, Acc, F). diff --git a/gen/test/gleam@any_test.erl b/gen/test/gleam@any_test.erl index c8deb45..e915fe7 100644 --- a/gen/test/gleam@any_test.erl +++ b/gen/test/gleam@any_test.erl @@ -151,14 +151,29 @@ struct2_test() -> field_test() -> {ok, OkAtom} = gleam@atom:from_string(<<"ok">>), + {ok, EarlierAtom} = gleam@atom:from_string(<<"earlier">>), gleam@expect:equal( - gleam@any:field(gleam@any:from(#{ok => 1}), OkAtom), + gleam@any:field( + gleam@any:from(gleam@map:put(gleam@map:new(), OkAtom, 1)), + OkAtom + ), {ok, gleam@any:from(1)} ), gleam@expect:equal( - gleam@any:field(gleam@any:from(#{earlier => 2, ok => 3}), OkAtom), + gleam@any:field( + gleam@any:from( + gleam@map:put( + gleam@map:put(gleam@map:new(), OkAtom, 3), + EarlierAtom, + 1 + ) + ), + OkAtom + ), {ok, gleam@any:from(3)} ), - gleam@expect:is_error(gleam@any:field(gleam@any:from(#{}), OkAtom)), + gleam@expect:is_error( + gleam@any:field(gleam@any:from(gleam@map:new()), OkAtom) + ), gleam@expect:is_error(gleam@any:field(gleam@any:from(1), OkAtom)), gleam@expect:is_error(gleam@any:field(gleam@any:from([]), [])). diff --git a/gen/test/gleam@map_dict_test.erl b/gen/test/gleam@map_dict_test.erl deleted file mode 100644 index 98c1486..0000000 --- a/gen/test/gleam@map_dict_test.erl +++ /dev/null @@ -1,157 +0,0 @@ --module(gleam@map_dict_test). --compile(no_auto_import). - --export([from_list_test/0, has_key_test/0, new_test/0, fetch_test/0, put_test/0, map_values_test/0, keys_test/0, values_test/0, take_test/0, drop_test/0, merge_test/0, delete_test/0, update_test/0, fold_test/0]). - -from_list_test() -> - gleam@expect:equal( - gleam@map_dict:size(gleam@map_dict:from_list([{4, 0}, {1, 0}])), - 2 - ). - -has_key_test() -> - gleam@expect:false(gleam@map_dict:has_key(gleam@map_dict:from_list([]), 1)), - gleam@expect:true( - gleam@map_dict:has_key(gleam@map_dict:from_list([{1, 0}]), 1) - ), - gleam@expect:true( - gleam@map_dict:has_key(gleam@map_dict:from_list([{4, 0}, {1, 0}]), 1) - ), - gleam@expect:false( - gleam@map_dict:has_key(gleam@map_dict:from_list([{4, 0}, {1, 0}]), 0) - ). - -new_test() -> - gleam@expect:equal(gleam@map_dict:size(gleam@map_dict:new()), 0), - gleam@expect:equal(gleam@map_dict:to_list(gleam@map_dict:new()), []). - -fetch_test() -> - Proplist = [{4, 0}, {1, 1}], - M = gleam@map_dict:from_list(Proplist), - gleam@expect:equal(gleam@map_dict:fetch(M, 4), {ok, 0}), - gleam@expect:equal(gleam@map_dict:fetch(M, 1), {ok, 1}), - gleam@expect:is_error(gleam@map_dict:fetch(M, 2)). - -put_test() -> - gleam@expect:equal( - gleam@map_dict:put( - gleam@map_dict:put( - gleam@map_dict:put(gleam@map_dict:new(), <<"a">>, 0), - <<"b">>, - 1 - ), - <<"c">>, - 2 - ), - gleam@map_dict:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]) - ). - -map_values_test() -> - gleam@expect:equal( - gleam@map_dict:map_values( - gleam@map_dict:from_list([{1, 0}, {2, 1}, {3, 2}]), - fun(K, V) -> K + V end - ), - gleam@map_dict:from_list([{1, 1}, {2, 3}, {3, 5}]) - ). - -keys_test() -> - gleam@expect:equal( - gleam@map_dict:keys( - gleam@map_dict:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]) - ), - [<<"a">>, <<"b">>, <<"c">>] - ). - -values_test() -> - gleam@expect:equal( - gleam@map_dict:values( - gleam@map_dict:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]) - ), - [0, 1, 2] - ). - -take_test() -> - gleam@expect:equal( - gleam@map_dict:take( - gleam@map_dict:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]), - [<<"a">>, <<"b">>, <<"d">>] - ), - gleam@map_dict:from_list([{<<"a">>, 0}, {<<"b">>, 1}]) - ). - -drop_test() -> - gleam@expect:equal( - gleam@map_dict:drop( - gleam@map_dict:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]), - [<<"a">>, <<"b">>, <<"d">>] - ), - gleam@map_dict:from_list([{<<"c">>, 2}]) - ). - -merge_test() -> - A = gleam@map_dict:from_list([{<<"a">>, 2}, {<<"c">>, 4}, {<<"d">>, 3}]), - B = gleam@map_dict:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]), - gleam@expect:equal( - gleam@map_dict:merge(A, B), - gleam@map_dict:from_list( - [{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}, {<<"d">>, 3}] - ) - ), - gleam@expect:equal( - gleam@map_dict:merge(B, A), - gleam@map_dict:from_list( - [{<<"a">>, 2}, {<<"b">>, 1}, {<<"c">>, 4}, {<<"d">>, 3}] - ) - ). - -delete_test() -> - gleam@expect:equal( - gleam@map_dict:delete( - gleam@map_dict:delete( - gleam@map_dict:from_list( - [{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}] - ), - <<"a">> - ), - <<"d">> - ), - gleam@map_dict:from_list([{<<"b">>, 1}, {<<"c">>, 2}]) - ). - -update_test() -> - Dict = gleam@map_dict:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]), - IncOrZero = fun(X) -> case X of - {ok, I} -> - I + 1; - - {error, _} -> - 0 - end end, - gleam@expect:equal( - gleam@map_dict:update(Dict, <<"a">>, IncOrZero), - gleam@map_dict:from_list([{<<"a">>, 1}, {<<"b">>, 1}, {<<"c">>, 2}]) - ), - gleam@expect:equal( - gleam@map_dict:update(Dict, <<"b">>, IncOrZero), - gleam@map_dict:from_list([{<<"a">>, 0}, {<<"b">>, 2}, {<<"c">>, 2}]) - ), - gleam@expect:equal( - gleam@map_dict:update(Dict, <<"z">>, IncOrZero), - gleam@map_dict:from_list( - [{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}, {<<"z">>, 0}] - ) - ). - -fold_test() -> - Dict = gleam@map_dict:from_list( - [{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}, {<<"d">>, 3}] - ), - Add = fun(_, V, Acc) -> V + Acc end, - gleam@expect:equal(gleam@map_dict:fold(Dict, 0, Add), 6), - Concat = fun(K, _, Acc) -> gleam@string:append(Acc, K) end, - gleam@expect:equal(gleam@map_dict:fold(Dict, <<"">>, Concat), <<"abcd">>), - gleam@expect:equal( - gleam@map_dict:fold(gleam@map_dict:from_list([]), 0, Add), - 0 - ). diff --git a/gen/test/gleam@map_test.erl b/gen/test/gleam@map_test.erl new file mode 100644 index 0000000..83a86f6 --- /dev/null +++ b/gen/test/gleam@map_test.erl @@ -0,0 +1,150 @@ +-module(gleam@map_test). +-compile(no_auto_import). + +-export([from_list_test/0, has_key_test/0, new_test/0, fetch_test/0, put_test/0, map_values_test/0, keys_test/0, values_test/0, take_test/0, drop_test/0, merge_test/0, delete_test/0, update_test/0, fold_test/0]). + +from_list_test() -> + gleam@expect:equal( + gleam@map:size(gleam@map:from_list([{4, 0}, {1, 0}])), + 2 + ). + +has_key_test() -> + gleam@expect:false(gleam@map:has_key(gleam@map:from_list([]), 1)), + gleam@expect:true(gleam@map:has_key(gleam@map:from_list([{1, 0}]), 1)), + gleam@expect:true( + gleam@map:has_key(gleam@map:from_list([{4, 0}, {1, 0}]), 1) + ), + gleam@expect:false( + gleam@map:has_key(gleam@map:from_list([{4, 0}, {1, 0}]), 0) + ). + +new_test() -> + gleam@expect:equal(gleam@map:size(gleam@map:new()), 0), + gleam@expect:equal(gleam@map:to_list(gleam@map:new()), []). + +fetch_test() -> + Proplist = [{4, 0}, {1, 1}], + M = gleam@map:from_list(Proplist), + gleam@expect:equal(gleam@map:fetch(M, 4), {ok, 0}), + gleam@expect:equal(gleam@map:fetch(M, 1), {ok, 1}), + gleam@expect:is_error(gleam@map:fetch(M, 2)). + +put_test() -> + gleam@expect:equal( + gleam@map:put( + gleam@map:put( + gleam@map:put(gleam@map:new(), <<"a">>, 0), + <<"b">>, + 1 + ), + <<"c">>, + 2 + ), + gleam@map:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]) + ). + +map_values_test() -> + gleam@expect:equal( + gleam@map:map_values( + gleam@map:from_list([{1, 0}, {2, 1}, {3, 2}]), + fun(K, V) -> K + V end + ), + gleam@map:from_list([{1, 1}, {2, 3}, {3, 5}]) + ). + +keys_test() -> + gleam@expect:equal( + gleam@map:keys( + gleam@map:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]) + ), + [<<"a">>, <<"b">>, <<"c">>] + ). + +values_test() -> + gleam@expect:equal( + gleam@map:values( + gleam@map:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]) + ), + [0, 1, 2] + ). + +take_test() -> + gleam@expect:equal( + gleam@map:take( + gleam@map:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]), + [<<"a">>, <<"b">>, <<"d">>] + ), + gleam@map:from_list([{<<"a">>, 0}, {<<"b">>, 1}]) + ). + +drop_test() -> + gleam@expect:equal( + gleam@map:drop( + gleam@map:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]), + [<<"a">>, <<"b">>, <<"d">>] + ), + gleam@map:from_list([{<<"c">>, 2}]) + ). + +merge_test() -> + A = gleam@map:from_list([{<<"a">>, 2}, {<<"c">>, 4}, {<<"d">>, 3}]), + B = gleam@map:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]), + gleam@expect:equal( + gleam@map:merge(A, B), + gleam@map:from_list( + [{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}, {<<"d">>, 3}] + ) + ), + gleam@expect:equal( + gleam@map:merge(B, A), + gleam@map:from_list( + [{<<"a">>, 2}, {<<"b">>, 1}, {<<"c">>, 4}, {<<"d">>, 3}] + ) + ). + +delete_test() -> + gleam@expect:equal( + gleam@map:delete( + gleam@map:delete( + gleam@map:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]), + <<"a">> + ), + <<"d">> + ), + gleam@map:from_list([{<<"b">>, 1}, {<<"c">>, 2}]) + ). + +update_test() -> + Dict = gleam@map:from_list([{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}]), + IncOrZero = fun(X) -> case X of + {ok, I} -> + I + 1; + + {error, _} -> + 0 + end end, + gleam@expect:equal( + gleam@map:update(Dict, <<"a">>, IncOrZero), + gleam@map:from_list([{<<"a">>, 1}, {<<"b">>, 1}, {<<"c">>, 2}]) + ), + gleam@expect:equal( + gleam@map:update(Dict, <<"b">>, IncOrZero), + gleam@map:from_list([{<<"a">>, 0}, {<<"b">>, 2}, {<<"c">>, 2}]) + ), + gleam@expect:equal( + gleam@map:update(Dict, <<"z">>, IncOrZero), + gleam@map:from_list( + [{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}, {<<"z">>, 0}] + ) + ). + +fold_test() -> + Dict = gleam@map:from_list( + [{<<"a">>, 0}, {<<"b">>, 1}, {<<"c">>, 2}, {<<"d">>, 3}] + ), + Add = fun(_, V, Acc) -> V + Acc end, + gleam@expect:equal(gleam@map:fold(Dict, 0, Add), 6), + Concat = fun(K, _, Acc) -> gleam@string:append(Acc, K) end, + gleam@expect:equal(gleam@map:fold(Dict, <<"">>, Concat), <<"abcd">>), + gleam@expect:equal(gleam@map:fold(gleam@map:from_list([]), 0, Add), 0). diff --git a/src/gleam/map.gleam b/src/gleam/map.gleam new file mode 100644 index 0000000..5e24816 --- /dev/null +++ b/src/gleam/map.gleam @@ -0,0 +1,100 @@ +import gleam/any +import gleam/result +import gleam/list + +pub external type MapDict(key, value); + +pub enum NotFound = + | NotFound + +pub external fn size(MapDict(k, v)) -> Int + = "maps" "size" + +pub external fn to_list(MapDict(key, value)) -> List(struct(key, value)) + = "maps" "to_list" + +pub external fn from_list(List(struct(key, value))) -> MapDict(key, value) + = "maps" "from_list" + +external fn is_key(key, MapDict(key, v)) -> Bool + = "maps" "is_key" + +pub fn has_key(map, key) { + is_key(key, map) +} + +pub external fn new() -> MapDict(key, value) + = "maps" "new" + +pub external fn fetch(MapDict(key, value), key) -> Result(value, NotFound) + = "gleam__stdlib" "map_fetch"; + +external fn erl_put(key, value, MapDict(key, value)) -> MapDict(key, value) + = "maps" "put"; + +pub fn put(map, key, value) { + erl_put(key, value, map) +} + +external fn erl_map_values(fn(key, value) -> value, MapDict(key, value)) + -> MapDict(key, value) + = "maps" "map"; + +pub fn map_values(map, fun) { + erl_map_values(fun, map) +} + +pub external fn keys(MapDict(keys, v)) -> List(keys) + = "maps" "keys" + +pub external fn values(MapDict(k, values)) -> List(values) + = "maps" "values" + +external fn erl_filter(fn(key, value) -> Bool, MapDict(key, value)) + -> MapDict(key, value) + = "maps" "filter"; + +pub fn filter(map, fun) { + erl_filter(fun, map) +} + +external fn erl_take(List(k), MapDict(k, v)) -> MapDict(k, v) = "maps" "with" + +pub fn take(map, keys) { + erl_take(keys, map) +} + +pub external fn merge(MapDict(k, v), MapDict(k, v)) -> MapDict(k, v) = "maps" "merge" + +external fn erl_delete(k, MapDict(k, v)) -> MapDict(k, v) = "maps" "remove" + +pub fn delete(map, key) { + erl_delete(key, map) +} + +pub fn drop(map, keys) { + list.fold(keys, map, fn(key, acc) { + delete(acc, key) + }) +} + +pub external type NotFound; + +pub fn update(dict, key, f) { + case fetch(dict, key) { + | Ok(value) -> put(dict, key, f(Ok(value))) + | Error(_) -> put(dict, key, f(Error(NotFound))) + } +} + +fn do_fold(list, acc, f) { + case list { + | [] -> acc + | [struct(k, v) | tail] -> do_fold(tail, f(k, v, acc), f) + } +} + +pub fn fold(dict, acc, f) { + let kvs = to_list(dict) + do_fold(kvs, acc, f) +} diff --git a/src/gleam/map_dict.gleam b/src/gleam/map_dict.gleam deleted file mode 100644 index 5e24816..0000000 --- a/src/gleam/map_dict.gleam +++ /dev/null @@ -1,100 +0,0 @@ -import gleam/any -import gleam/result -import gleam/list - -pub external type MapDict(key, value); - -pub enum NotFound = - | NotFound - -pub external fn size(MapDict(k, v)) -> Int - = "maps" "size" - -pub external fn to_list(MapDict(key, value)) -> List(struct(key, value)) - = "maps" "to_list" - -pub external fn from_list(List(struct(key, value))) -> MapDict(key, value) - = "maps" "from_list" - -external fn is_key(key, MapDict(key, v)) -> Bool - = "maps" "is_key" - -pub fn has_key(map, key) { - is_key(key, map) -} - -pub external fn new() -> MapDict(key, value) - = "maps" "new" - -pub external fn fetch(MapDict(key, value), key) -> Result(value, NotFound) - = "gleam__stdlib" "map_fetch"; - -external fn erl_put(key, value, MapDict(key, value)) -> MapDict(key, value) - = "maps" "put"; - -pub fn put(map, key, value) { - erl_put(key, value, map) -} - -external fn erl_map_values(fn(key, value) -> value, MapDict(key, value)) - -> MapDict(key, value) - = "maps" "map"; - -pub fn map_values(map, fun) { - erl_map_values(fun, map) -} - -pub external fn keys(MapDict(keys, v)) -> List(keys) - = "maps" "keys" - -pub external fn values(MapDict(k, values)) -> List(values) - = "maps" "values" - -external fn erl_filter(fn(key, value) -> Bool, MapDict(key, value)) - -> MapDict(key, value) - = "maps" "filter"; - -pub fn filter(map, fun) { - erl_filter(fun, map) -} - -external fn erl_take(List(k), MapDict(k, v)) -> MapDict(k, v) = "maps" "with" - -pub fn take(map, keys) { - erl_take(keys, map) -} - -pub external fn merge(MapDict(k, v), MapDict(k, v)) -> MapDict(k, v) = "maps" "merge" - -external fn erl_delete(k, MapDict(k, v)) -> MapDict(k, v) = "maps" "remove" - -pub fn delete(map, key) { - erl_delete(key, map) -} - -pub fn drop(map, keys) { - list.fold(keys, map, fn(key, acc) { - delete(acc, key) - }) -} - -pub external type NotFound; - -pub fn update(dict, key, f) { - case fetch(dict, key) { - | Ok(value) -> put(dict, key, f(Ok(value))) - | Error(_) -> put(dict, key, f(Error(NotFound))) - } -} - -fn do_fold(list, acc, f) { - case list { - | [] -> acc - | [struct(k, v) | tail] -> do_fold(tail, f(k, v, acc), f) - } -} - -pub fn fold(dict, acc, f) { - let kvs = to_list(dict) - do_fold(kvs, acc, f) -} diff --git a/test/gleam/any_test.gleam b/test/gleam/any_test.gleam index ef441d7..13af0cb 100644 --- a/test/gleam/any_test.gleam +++ b/test/gleam/any_test.gleam @@ -4,6 +4,7 @@ import gleam/list import gleam/tuple import gleam/expect import gleam/result +import gleam/map pub fn string_test() { "" @@ -250,18 +251,22 @@ pub fn struct2_test() { pub fn field_test() { let Ok(ok_atom) = atom.from_string("ok") + let Ok(earlier_atom) = atom.from_string("earlier") - {ok = 1} + map.new() + |> map.put(_, ok_atom, 1) |> any.from |> any.field(_, ok_atom) |> expect.equal(_, Ok(any.from(1))) - {earlier = 2, ok = 3} + map.new() + |> map.put(_, ok_atom, 3) + |> map.put(_, earlier_atom, 1) |> any.from |> any.field(_, ok_atom) |> expect.equal(_, Ok(any.from(3))) - {} + map.new() |> any.from |> any.field(_, ok_atom) |> expect.is_error diff --git a/test/gleam/map_dict_test.gleam b/test/gleam/map_dict_test.gleam deleted file mode 100644 index a258067..0000000 --- a/test/gleam/map_dict_test.gleam +++ /dev/null @@ -1,254 +0,0 @@ -import gleam/string -import gleam/expect -import gleam/map_dict - -pub fn from_list_test() { - [ - struct(4, 0), - struct(1, 0), - ] - |> map_dict.from_list - |> map_dict.size - |> expect.equal(_, 2) -} - -pub fn has_key_test() { - [] - |> map_dict.from_list - |> map_dict.has_key(_, 1) - |> expect.false - - [ - struct(1, 0), - ] - |> map_dict.from_list - |> map_dict.has_key(_, 1) - |> expect.true - - [ - struct(4, 0), - struct(1, 0), - ] - |> map_dict.from_list - |> map_dict.has_key(_, 1) - |> expect.true - - [ - struct(4, 0), - struct(1, 0), - ] - |> map_dict.from_list - |> map_dict.has_key(_, 0) - |> expect.false -} - -pub fn new_test() { - map_dict.new() - |> map_dict.size - |> expect.equal(_, 0) - - map_dict.new() - |> map_dict.to_list - |> expect.equal(_, []) -} - -pub fn fetch_test() { - let proplist = [ - struct(4, 0), - struct(1, 1), - ] - let m = map_dict.from_list(proplist) - - m - |> map_dict.fetch(_, 4) - |> expect.equal(_, Ok(0)) - - m - |> map_dict.fetch(_, 1) - |> expect.equal(_, Ok(1)) - - m - |> map_dict.fetch(_, 2) - |> expect.is_error -} - -pub fn put_test() { - map_dict.new() - |> map_dict.put(_, "a", 0) - |> map_dict.put(_, "b", 1) - |> map_dict.put(_, "c", 2) - |> expect.equal(_, map_dict.from_list([ - struct("a", 0), - struct("b", 1), - struct("c", 2), - ])) -} - -pub fn map_values_test() { - [ - struct(1, 0), - struct(2, 1), - struct(3, 2), - ] - |> map_dict.from_list - |> map_dict.map_values(_, fn(k, v) { k + v }) - |> expect.equal(_, map_dict.from_list([ - struct(1, 1), - struct(2, 3), - struct(3, 5), - ])) -} - -pub fn keys_test() { - [ - struct("a", 0), - struct("b", 1), - struct("c", 2), - ] - |> map_dict.from_list - |> map_dict.keys - |> expect.equal(_, ["a", "b", "c"]) -} - -pub fn values_test() { - [ - struct("a", 0), - struct("b", 1), - struct("c", 2), - ] - |> map_dict.from_list - |> map_dict.values - |> expect.equal(_, [0, 1, 2]) -} - -pub fn take_test() { - [ - struct("a", 0), - struct("b", 1), - struct("c", 2), - ] - |> map_dict.from_list - |> map_dict.take(_, ["a", "b", "d"]) - |> expect.equal(_, map_dict.from_list([struct("a", 0), struct("b", 1)])) -} - -pub fn drop_test() { - [ - struct("a", 0), - struct("b", 1), - struct("c", 2), - ] - |> map_dict.from_list - |> map_dict.drop(_, ["a", "b", "d"]) - |> expect.equal(_, map_dict.from_list([struct("c", 2)])) -} - -pub fn merge_test() { - let a = map_dict.from_list([ - struct("a", 2), - struct("c", 4), - struct("d", 3), - ]) - let b = map_dict.from_list([ - struct("a", 0), - struct("b", 1), - struct("c", 2), - ]) - - map_dict.merge(a, b) - |> expect.equal(_, map_dict.from_list([ - struct("a", 0), - struct("b", 1), - struct("c", 2), - struct("d", 3), - ])) - - map_dict.merge(b, a) - |> expect.equal(_, map_dict.from_list([ - struct("a", 2), - struct("b", 1), - struct("c", 4), - struct("d", 3), - ])) -} - -pub fn delete_test() { - [ - struct("a", 0), - struct("b", 1), - struct("c", 2), - ] - |> map_dict.from_list - |> map_dict.delete(_, "a") - |> map_dict.delete(_, "d") - |> expect.equal(_, map_dict.from_list([struct("b", 1), struct("c", 2)])) -} - -pub fn update_test() { - let dict = map_dict.from_list([ - struct("a", 0), - struct("b", 1), - struct("c", 2), - ]) - - let inc_or_zero = fn(x) { - case x { - | Ok(i) -> i + 1 - | Error(_) -> 0 - } - } - - dict - |> map_dict.update(_, "a", inc_or_zero) - |> expect.equal(_, map_dict.from_list([ - struct("a", 1), - struct("b", 1), - struct("c", 2), - ])) - - dict - |> map_dict.update(_, "b", inc_or_zero) - |> expect.equal(_, map_dict.from_list([ - struct("a", 0), - struct("b", 2), - struct("c", 2), - ])) - - dict - |> map_dict.update(_, "z", inc_or_zero) - |> expect.equal(_, map_dict.from_list([ - struct("a", 0), - struct("b", 1), - struct("c", 2), - struct("z", 0), - ])) -} - -pub fn fold_test() { - let dict = map_dict.from_list([ - struct("a", 0), - struct("b", 1), - struct("c", 2), - struct("d", 3), - ]) - - let add = fn(_, v, acc) { - v + acc - } - - dict - |> map_dict.fold(_, 0, add) - |> expect.equal(_, 6) - - let concat = fn(k, _, acc) { - string.append(acc, k) - } - - dict - |> map_dict.fold(_, "", concat) - |> expect.equal(_, "abcd") - - map_dict.from_list([]) - |> map_dict.fold(_, 0, add) - |> expect.equal(_, 0) -} diff --git a/test/gleam/map_test.gleam b/test/gleam/map_test.gleam new file mode 100644 index 0000000..529afe2 --- /dev/null +++ b/test/gleam/map_test.gleam @@ -0,0 +1,254 @@ +import gleam/string +import gleam/expect +import gleam/map + +pub fn from_list_test() { + [ + struct(4, 0), + struct(1, 0), + ] + |> map.from_list + |> map.size + |> expect.equal(_, 2) +} + +pub fn has_key_test() { + [] + |> map.from_list + |> map.has_key(_, 1) + |> expect.false + + [ + struct(1, 0), + ] + |> map.from_list + |> map.has_key(_, 1) + |> expect.true + + [ + struct(4, 0), + struct(1, 0), + ] + |> map.from_list + |> map.has_key(_, 1) + |> expect.true + + [ + struct(4, 0), + struct(1, 0), + ] + |> map.from_list + |> map.has_key(_, 0) + |> expect.false +} + +pub fn new_test() { + map.new() + |> map.size + |> expect.equal(_, 0) + + map.new() + |> map.to_list + |> expect.equal(_, []) +} + +pub fn fetch_test() { + let proplist = [ + struct(4, 0), + struct(1, 1), + ] + let m = map.from_list(proplist) + + m + |> map.fetch(_, 4) + |> expect.equal(_, Ok(0)) + + m + |> map.fetch(_, 1) + |> expect.equal(_, Ok(1)) + + m + |> map.fetch(_, 2) + |> expect.is_error +} + +pub fn put_test() { + map.new() + |> map.put(_, "a", 0) + |> map.put(_, "b", 1) + |> map.put(_, "c", 2) + |> expect.equal(_, map.from_list([ + struct("a", 0), + struct("b", 1), + struct("c", 2), + ])) +} + +pub fn map_values_test() { + [ + struct(1, 0), + struct(2, 1), + struct(3, 2), + ] + |> map.from_list + |> map.map_values(_, fn(k, v) { k + v }) + |> expect.equal(_, map.from_list([ + struct(1, 1), + struct(2, 3), + struct(3, 5), + ])) +} + +pub fn keys_test() { + [ + struct("a", 0), + struct("b", 1), + struct("c", 2), + ] + |> map.from_list + |> map.keys + |> expect.equal(_, ["a", "b", "c"]) +} + +pub fn values_test() { + [ + struct("a", 0), + struct("b", 1), + struct("c", 2), + ] + |> map.from_list + |> map.values + |> expect.equal(_, [0, 1, 2]) +} + +pub fn take_test() { + [ + struct("a", 0), + struct("b", 1), + struct("c", 2), + ] + |> map.from_list + |> map.take(_, ["a", "b", "d"]) + |> expect.equal(_, map.from_list([struct("a", 0), struct("b", 1)])) +} + +pub fn drop_test() { + [ + struct("a", 0), + struct("b", 1), + struct("c", 2), + ] + |> map.from_list + |> map.drop(_, ["a", "b", "d"]) + |> expect.equal(_, map.from_list([struct("c", 2)])) +} + +pub fn merge_test() { + let a = map.from_list([ + struct("a", 2), + struct("c", 4), + struct("d", 3), + ]) + let b = map.from_list([ + struct("a", 0), + struct("b", 1), + struct("c", 2), + ]) + + map.merge(a, b) + |> expect.equal(_, map.from_list([ + struct("a", 0), + struct("b", 1), + struct("c", 2), + struct("d", 3), + ])) + + map.merge(b, a) + |> expect.equal(_, map.from_list([ + struct("a", 2), + struct("b", 1), + struct("c", 4), + struct("d", 3), + ])) +} + +pub fn delete_test() { + [ + struct("a", 0), + struct("b", 1), + struct("c", 2), + ] + |> map.from_list + |> map.delete(_, "a") + |> map.delete(_, "d") + |> expect.equal(_, map.from_list([struct("b", 1), struct("c", 2)])) +} + +pub fn update_test() { + let dict = map.from_list([ + struct("a", 0), + struct("b", 1), + struct("c", 2), + ]) + + let inc_or_zero = fn(x) { + case x { + | Ok(i) -> i + 1 + | Error(_) -> 0 + } + } + + dict + |> map.update(_, "a", inc_or_zero) + |> expect.equal(_, map.from_list([ + struct("a", 1), + struct("b", 1), + struct("c", 2), + ])) + + dict + |> map.update(_, "b", inc_or_zero) + |> expect.equal(_, map.from_list([ + struct("a", 0), + struct("b", 2), + struct("c", 2), + ])) + + dict + |> map.update(_, "z", inc_or_zero) + |> expect.equal(_, map.from_list([ + struct("a", 0), + struct("b", 1), + struct("c", 2), + struct("z", 0), + ])) +} + +pub fn fold_test() { + let dict = map.from_list([ + struct("a", 0), + struct("b", 1), + struct("c", 2), + struct("d", 3), + ]) + + let add = fn(_, v, acc) { + v + acc + } + + dict + |> map.fold(_, 0, add) + |> expect.equal(_, 6) + + let concat = fn(k, _, acc) { + string.append(acc, k) + } + + dict + |> map.fold(_, "", concat) + |> expect.equal(_, "abcd") + + map.from_list([]) + |> map.fold(_, 0, add) + |> expect.equal(_, 0) +} -- cgit v1.2.3