| 1 | -module(hope_list). |
| 2 | |
| 3 | -export_type( |
| 4 | [ t/1 |
| 5 | ]). |
| 6 | |
| 7 | -export( |
| 8 | [ unique_preserve_order/1 |
| 9 | , map_rev/2 |
| 10 | ]). |
| 11 | |
| 12 | |
| 13 | -type t(A) :: |
| 14 | [A]. |
| 15 | |
| 16 | |
| 17 | %% @doc O(N), tail-recursive equivalent to lists:rev(lists:map(F, L)) |
| 18 | %% @end |
| 19 | -spec map_rev([A], fun((A) -> (B))) -> |
| 20 | [B]. |
| 21 | map_rev(Xs, F) -> |
| 22 | map_rev_acc(Xs, F, []). |
| 23 | |
| 24 | -spec map_rev_acc([A], fun((A) -> (B)), [B]) -> |
| 25 | [B]. |
| 26 | map_rev_acc([], _, Ys) -> |
| 27 | Ys; |
| 28 | map_rev_acc([X|Xs], F, Ys) -> |
| 29 | Y = F(X), |
| 30 | map_rev_acc(Xs, F, [Y|Ys]). |
| 31 | |
| 32 | |
| 33 | -spec unique_preserve_order(t(A)) -> |
| 34 | t(A). |
| 35 | unique_preserve_order(L) -> |
| 36 | PrependIfNew = |
| 37 | fun (X, Xs) -> |
| 38 | case lists:member(X, Xs) |
| 39 | of true -> Xs |
| 40 | ; false -> [X | Xs] |
| 41 | end |
| 42 | end, |
| 43 | lists:reverse(lists:foldl(PrependIfNew, [], L)). |