-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlist_ops.exs
30 lines (23 loc) · 1.12 KB
/
list_ops.exs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
defmodule ListOps do
# Please don't use any external modules (especially List or Enum) in your
# implementation. The point of this exercise is to create these basic
# functions yourself. You may use basic Kernel functions (like `Kernel.+/2`
# for adding numbers), but please do not use Kernel functions for Lists like
# `++`, `--`, `hd`, `tl`, `in`, and `length`.
@spec count(list) :: non_neg_integer
def count(l), do: reduce(l, 0, fn _, c -> c + 1 end)
@spec reverse(list) :: list
def reverse(l), do: reduce(l, [], &[&1 | &2])
@spec map(list, (any -> any)) :: list
def map(l, f), do: l |> reduce([], &[f.(&1) | &2]) |> reverse
@spec filter(list, (any -> as_boolean(term))) :: list
def filter(l, f), do: reduce(l, [], &(f.(&1) && [&1 | &2] || &2)) |> reverse
@type acc :: any
@spec reduce(list, acc, (any, acc -> acc)) :: acc
def reduce([h|t], acc, f), do: reduce(t, f.(h, acc), f)
def reduce([], acc, _), do: acc
@spec append(list, list) :: list
def append(a, b), do: a |> reverse |> reduce(b, &[&1 | &2])
@spec concat([[any]]) :: [any]
def concat(ll), do: ll |> reverse |> reduce([], &append/2)
end