Skip to content

Instantly share code, notes, and snippets.

@diogovk
Created January 30, 2014 00:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save diogovk/8700256 to your computer and use it in GitHub Desktop.
Save diogovk/8700256 to your computer and use it in GitHub Desktop.
compares the speed of concat using append, and recursive version.
defmodule ListOps do
# Please don't use any external modules (especially List) in your
# implementation. The point of this exercise is to create these basic functions
# yourself.
#
# Note that `++` is a function from an external module (Kernel, which is
# automatically important`) and so shouldn't be used either.
@spec count(list) :: non_neg_integer
def count(l) do
do_count(l,0)
end
defp do_count([], acc), do: acc
defp do_count([_head|tail], acc) do
do_count(tail,acc+1)
end
@spec reverse(list) :: list
def reverse(l) do
do_reverse(l,[])
end
defp do_reverse([], acc), do: acc
defp do_reverse([head|tail], acc) do
do_reverse(tail, [head|acc])
end
@spec map(list, (any -> any)) :: list
def map(l, f) do
reverse do_map(l, f, [])
end
defp do_map([],_, acc), do: acc
defp do_map([head|tail], f, acc) do
do_map(tail, f, [f.(head)|acc])
end
@spec filter(list, (any -> as_boolean(term))) :: list
def filter(l, f) do
reverse do_filter(l, f, [])
end
defp do_filter([], _, acc), do: acc
defp do_filter([head|tail], f, acc) do
if f.(head) do
do_filter(tail, f, [head|acc])
else
do_filter(tail, f, acc)
end
end
@type acc :: any
@spec reduce(list, acc, ((any, acc) -> acc)) :: acc
def reduce(l, acc, f) do
do_reduce(l, acc, f)
end
defp do_reduce([], acc, _), do: acc
defp do_reduce([head|tail], acc, f) do
do_reduce(tail, f.(head, acc), f)
end
@spec append(list, list) :: list
def append(a, b) do
do_append reverse(a), b
end
def do_append([], acc), do: acc
def do_append([head|tail], acc) do
do_append(tail,[head|acc])
end
@spec concat([[any]]) :: [any]
def concat([]), do: []
def concat(enums) do
reverse do_concat(enums, [])
end
defp do_concat([], acc) do
acc
end
defp do_concat([[]|tail], acc) do
do_concat(tail, acc)
end
defp do_concat([ [first_head|first_tail] | tail ], acc) do
do_concat([first_tail | tail], [first_head|acc])
end
@spec concat_a([[any]]) :: [any]
def concat_a(ll) do
reverse(ll) |>
reduce([], &(append(&2, &1)))
end
def test1() do
concat(Enum.map(1..50000, &[&1]))
end
def test2() do
concat_a(Enum.map(1..50000, &[&1]))
end
end
IO.inspect(:timer.tc ListOps, :test1, [] )
IO.inspect(:timer.tc ListOps, :test2, [] )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment