small medium large xlarge

• Implement the following Enum functions using no library functions or list comprehensions: `all?`, `each`, `filter`, `split`, and `take`

A Possible Solution</summary>

```defmodule MyList do

def all?(list),     do: all?(list, fn x -> !!x end) # !! converts truthy to `true`
def all?([], _fun), do: true
def all?([ head | tail ], fun) do
all?(tail, fun)
else
false
end
end

def each([], _fun), do: []
def each([ head | tail ], fun) do
[ fun.(head) | each(tail, fun) ]
end

def filter([], _fun), do: []
def filter([ head | tail ], fun) do
else
[ filter(tail, fun) ]
end
end

def split(list, count),      do: _split(list, [], count)
defp _split([], front, _),   do: [ Enum.reverse(front), [] ]
defp _split(tail, front, 0), do: [ Enum.reverse(front), tail ]
defp _split([ head | tail ], front, count)  do
end

def take(list, n), do: hd(split(list, n))

end

IO.inspect MyList.all?([])                 #=> true
IO.inspect MyList.all?([true, true])       #=> true
IO.inspect MyList.all?([true, false])      #=> false
IO.inspect MyList.all?([4, 5, 6], &1 > 3)  #=> true

MyList.each([1,2,3], IO.puts(&1))          #=> 1/2/3

IO.inspect MyList.split([1,2,3,4,5,6], 3)  #=> [[1, 2, 3], [4, 5, 6]]

IO.inspect MyList.take('pragmatic', 6)     #=> 'pragma'
```

</details>

Hi Dave

Maybe this is done intentionally to check who is doing exercises and checks with the answers :), but still looks like there are couple issues in this solution

`Enum.each` executes the function for each element in the list and returns :ok. `MyList.each` instead collects all function results in a list (sort of like Enum.map does) and returns it, thus we get:

``````iex(102)> Enum.each([1,2,3,4],IO.puts(&1))
1
2
3
4
:ok
iex(103)> MyList1.each([1,2,3,4],IO.puts(&1))
1
2
3
4
[:ok, :ok, :ok, :ok]
``````

So no need to add the results into the list, this implementation seems to work right:

``````def each([],fun), do: :ok
def each([h|t],fun) do
fun.(h)
each(t,fun)
end
``````

In `filter` implementation you are creating nested lists, because there is a coma used where a join operator is needed, and also in the else: case you do not need to nest the call to `filter(tail, fun)` into `[]`. Here is the test output:

``````iex(104)> Enum.filter([1,2,3,4],fn x -> rem(x,2)==0 end)
[2, 4]
iex(105)> MyList1.filter([1,2,3,4],fn x -> rem(x,2)==0 end)
[[2, [[4, []]]]]
``````

My implementation looks like this (I was trying to omit using the `if else`, thus the code is a bit ugly, I guess `if else` is better to use instead of pattern matching in this case, and also it would allow to not use accumulator):

``````def filter(list,fun), do: do_filter(list,fun,[])

defp do_filter([],fun,acc), do: Enum.reverse acc

defp do_filter([h|t],fun,acc) do
do_filter(t,fun,acc)
end

``````

`Enum.split` produces a tuple as a result, while `MyList.split` creates a list. Also `Enum.split` works with negative numbers as well, by cutting it from the right. Here is the solution that handles the negatives:

``````#Enum.split
def split(list,n), do:  do_split([],list,n)
n = n+length(tail)
if n<0 do
n = 0
end
end
end

``````

Yeah not so sure about the `filter` implementation provided as mentioned by Eugene it yields nested lists. Mine looks like:

``````def filter([], _func), do: []
def filter([head | tail], func) do
else
[] ++ filter(tail, func)
end
end
``````

Dave K., while your implementation looks like it will work, it seems to be suboptimal, since your filter function will not be a subject to the tail call optimization, because it is not the last thing executed in the filter function body (instead the concatenation operator Kernel.++ is).

In Elixir, Erlang and I think other functional languages it is super-important to pay attention that your recursive call is the last thing you do in the function body, otherwise - you are risking to get a stack overflow. That’s why the accumulators are needed. I don’t remember if the book mentions this, however there is an excellent screencast with Jose Valim here: https://peepcode.com/products/elixir - where he mentions this tail call optimization and other things.

Also suboptimality comes from using list concatenation on every step. when you do join h | t , you always reuse the tail. Then you do Enum.reverse only once. And this is much cheaper, than creating a new list on every step and copy all items from both concatenated lists into it (this is how Kernel.++/2 seems to work, although I might be wrong, need to check that).

My implementation for split

``````    def split(list, count), do: _split(list,[], count)

defp _split(_list, acc, 0), do: [Enum.reverse(acc), _list]

defp _split([], acc, count) when count < 0  do
[acc, []]
end
defp _split([], acc, count), do: [Enum.reverse(acc), []]

defp _split([head|tail], acc, count) when count > 0 do
end

defp _split(list, acc, count) when count < 0 do
result = _split(Enum.reverse(tail), [head|acc], count + 1)
Enum.reverse(result)
end
``````

I used following test cases: http://elixir-lang.org/docs/stable/Enum.html#split/2

My version of all? without using if/else:

``````def all?(list), do: all?(list, fn x -> !!x end)
def all?([], _), do: true
``````

I found some unit tests were really helpful for building these methods. My test for `#each` doesn’t test that the function actually gets called. Just run this file as a script:

`\$ elixir my-list_test.exs`

```# my-list_test.exs
require Integer

ExUnit.start

defmodule MyListTest do
use ExUnit.Case

test "all? is true" do
expected = MyList.all?([1,2,3], &(&1))
assert expected
end

test "all? is false" do
expected = MyList.all?([1,2,3], &(&1 == 1))
assert expected == false
end

test "each function is invoked" do
expected = MyList.each([1,2,3], &(&1 == 1))
assert expected == :ok
end

test "filter returns matching elements" do
expected = MyList.filter([1,2,3], &(Integer.odd?(&1)))
assert expected == [1, 3]
end

test "split cuts the collection in two" do
expected = MyList.split([1,2,3,4],1)
assert expected == {[1], [2, 3, 4]}
end

test "take the first few items" do
expected = MyList.take([1,2,3,4],1)
assert expected == [1]
end
end
```

My approach for `split` and `take`:

``````defmodule MyList
def split([head | tail], count) when count > 0 do
{left, right} = split(tail, count-1)
end
def split(list, _count), do: {[], list}

def take([head | tail], count) when count > 0 do
end
def take(_list, _count), do: []
end
``````

If you want `take` to work with negative indices like `Enum.take`:

``````defmodule MyList
def take(list, count) when count < 0 do
Enum.reverse take(Enum.reverse(list), -count)
end
def take([head | tail], count) do
end
def take(_list, _count), do: []
end
``````

Here are my split and take which handle the negative indices in a way I haven’t yet seen.

``````defmodule MyList do
def split(list, 0),             do: {[], list}
def split([], _count),          do: {[], []}
def split([head | tail], count) when count > 0 do
{first, rest} = split(tail, count - 1)
end
def split(list, count) do
{first, rest, _rest_size}  = _rsplit(list, -count)
{first, rest}
end

defp _rsplit([], _count), do: {[],[], 0}
defp _rsplit([head | tail], count) do
{first, rest, rest_size}  = _rsplit(tail, count)
if (rest_size < count) do
else
end
end

def take(_list, 0),    do: []
def take([], _count), do: []
def take([head|tail], count) when count > 0 do
end
def take(list, count) do
{first, _rest_size} = _rtake(list, -count)
first
end

defp _rtake([], _count), do: {[], 0}
{rest, rest_size}  = _rtake(tail, count)
if (rest_size < count) do
else
{rest, rest_size}
end
end
end
``````

I’m posting my solution here, for the sake of discussion, because it’s different from what’s been posted so far.

My split() function projects the negative-count case onto the positive-count case in one fell swoop using max():

```  def split(collection, count) when count < 0 do
split(collection, max(0, length(collection) + count))
end
def split(collection, 0), do: { [], collection }
{ left, right } = split(tail, count - 1)
end
def split([], _count), do: { [], [] }
```

My take() function simply re-uses my split() function from above:

```  def take(collection, count) do
{ left, right } = split(collection, count)
if count < 0 do
right
else
left
end
end
```

I don’t get why this approach to `split` fails to assign new values to the lists `left` and `right`. Am I using the `for i <- list` syntax correctly?

```  def split(list, 0), do: {[], list}
def split(list, count) when count > 0 do
{ left, right } = { [], [] }
if count > length(list) - 1 do
{ list, [] }
else
for l <- (0 .. count - 1), do: left = left ++ [Enum.at(list, l)]
for r <- (count .. length(list) - 1), do: right = right ++ [Enum.at(list, r)]
{ left, right }
end
end
def split(list, count) when count < 0 do
{ left, right } = { [], [] }
if abs(count) > length(list) - 1 do
{ [], list }
else
for l <- (0 .. length(list) - 1 + count), do: left = left ++ [Enum.at(list, l)]
for r <- (length(list) + count .. length(list)), do: right = right ++ [Enum.at(list, r)]
{ left, right }
end
end
```
``````defmodule MyEnum do

# all?
def all?([], _func), do: true
end

# each
def each([], _func), do: :ok
each(tail, func)
end

# filter
def filter([], _func), do: []
else
filter(tail, func)
end
end

# split
def split([], _count), do: {[],[]}
def split(collection, count)
when count > length(collection), do: {collection, []}
def split(collection, count)
when abs(count) > length(collection) or count == 0, do: {[], collection}
def split(collection, count) do
if count > 0 do
first = _split(collection, count)
else
first = _split(collection, length(collection) + count)
end
{first, collection -- first}
end
defp _split(_, count) when count == 0, do: []

# take
def take(collection, count)
when abs(count) >= length(collection), do: collection
def take(collection, count) when count < 0 do
collection -- _take(collection, length(collection)+count)
end
def take(collection, count), do: _take(collection, count)
def _take(collection, count) when count == 0 or collection == [], do: []
end
``````

My solution for `split` and `take` are in the same line as Suraj’s. I like his use of `max()`, which can reduce an extra pattern matching conditional method in mine.

```defmodule MyList do

defp type_check(x) when is_nil(x), do: false
defp type_check(x), do: x

def all?(list, func \\ &type_check/1)

def all?([], _), do: true

def all?([head | tail], func) do
end

def each([], _), do: :ok

MyList.each(tail, func)
end

def filter([], _), do: []

def filter([head | tail], func) do
else
MyList.filter(tail, func)
end
end

defp move_item(target, source, count) when count == 0 or length(source) == 0 do
{target, source}
end

defp move_item(target, [head | tail], count) do
move_item(target ++ [head], tail, count - 1)
end

def split([], _), do: {[], []}

def split(list, count) when count < 0 and length(list) <= abs(count) do
{[], list}
end

def split(list, count) when count < 0 do
split(list, length(list) + count)
end

def split(list, count) do
move_item([], list, count)
end

def take([], _) do
[]
end

def take(list, count) when count < 0 and length(list) < abs(count) do
list
end

def take(list, count) when count < 0 do
{_, rhs} = move_item([], list, length(list) + count)
rhs
end

def take(list, count) do
{lhs, _} = move_item([], list, count)
lhs
end

end

```
``````defmodule MyEnum do

# all?
def all?([], _), do: true
def all?(list, fun), do: _all?(list, true, fun)
defp _all?(_, false, _), do: false
defp _all?([], true, _), do: true
defp _all?([h|t], _, fun), do: _all?(t, fun.(h), fun)

# each
def each([], _), do: :ok
def each([h|t], fun) do
fun.(h)
each(t, fun)
end

# filter
def filter([], _), do: []
def filter(list, fun), do: _filter(list, [], fun)
defp _filter([], res, _), do: :lists.reverse res
defp _filter([h|t], res, fun) do
if fun.(h) do
_filter(t, [h | res], fun)
else
_filter(t, res, fun)
end
end

# split
def split([], _), do: {[], []}
def split(list, 0), do: {[], list}
def split([h|t], n), do: _split({[h], t}, 1, n)
defp _split({l1, l2}, cnt, n) when cnt == n or l2 == [], do: {:lists.reverse(l1), l2}
defp _split({l1, [h|t]}, cnt, n), do: _split({[h|l1], t}, cnt+1, n)

# take
def take([], _), do: []
def take(_, 0), do: []
def take([h|t], n), do: _take([h], t, 1, n)
defp _take(res, rem, cnt, n) when cnt == n or rem == [], do: :lists.reverse res
defp _take(res, [h|t], cnt, n), do: _take([h | res], t, cnt+1, n)
end
``````

all? Is this confusing or what? ~~~elixir def all?(list), do: all?(list, fn x -> !!x end) # !! converts truthy to true ~~~

AND he uses an if statement, even though he only mentions it might be necessary for filter! Anyway, here’s my solution, pretty readable and seems to work without truthy conversions

```def all?([], _), do: true
```

each Eugene already mentioned what I was going to say for this, my answer is the same as most:

```def each([],_), do: :ok
each(tail, func)
end
```

filter There is some conversation on this in the thread, and some invalid answers. Remember, the instructions said “using no library functions or list comprehensions” so you aren’t supposed to use Enum.reverse/1. I think Dave T. just made a typo in his answer, accidentally putting comma where he meant a pipe. My answer is the same as others:

```def filter([], _func), do: []
else
filter(tail, func)
end
end
```

split This time even Dave used Enum.reverse/1! Am I misunderstanding what “library function” means here? Figuring out the answer for non-negative counts is pretty easy, but getting negative counts without using library functions is very hard. You can see the above all use some function or another.

I’m glad I wasn’t the only one baffled by all the responses using library functions, when the task specifically says “don’t use any”.

I’m not sure about the use of

``````def all?(list), do: all?(list, fn x -> !!x end) # !! converts truthy to true
``````

either, tbh.

I like the optimization of returning `false` in `all?` if `fun.(head)` is false. Didn’t think of that one.

Here is my implementation of split. I have tried to be away from any library functions. It does not handle negative count yet. And it’s not very efficient as well.

``````def my_split([], _),       do: {[], []}
def my_split(list, 0),     do: {[], list}
def my_split(list, count), do: {left(list, count), right(list, count)}

def left(_list, 0), do: []
def left([], _count), do: []
def left([head | tail], count) do
[head] ++ left(tail, count - 1)
end

def right(list, 0), do: list
def right([], _count), do: []
def right([_head | tail], count) do
[] ++ right(tail, count - 1)
end
``````

My implementation of `split` uses string concatenation, like so: `defp _split([ head | tail ], count, acc), do: _split(tail, count - 1, acc ++ [ head])`.

To do split with no library functions, I just implemented count:

``````  def split([], _), do: {[], []}
def split(collection, 0), do: {[], collection}
def split([ head | tail ], count) when count > 0 do
{left, right} =  split(tail, count-1)
end
def split(collection, count) when count < 0 do
len = _len(collection)
pos = len + count
if pos < 0 do
split(collection, 0)
else
split(collection, pos)
end
end
def _len([]), do: 0
def _len([ _ | [] ]), do: 1
def _len([ _ | tail ]), do: 1 + _len(tail)
``````

But, I think the approaches that use an accumulator to build the tail of the list are better because I think they are tail-first.

Here are my implementations of all?, each and filter. Some of them may seem to be a little complicated, but I was using only function head matching and basic operations.

``````defmodule Awesome do

# all?

def all?(collection, fun \\ fn x -> x end) when is_list(collection) do
_all?(collection, fun, true)
end

defp _all?([], _, match) when match === true, do: true
defp _all?(_, _, match) when match === false, do: false
defp _all?([ head | tail ], fun, _match) do
_all?(tail, fun, match_tmp)
end

# each

def each(collection, fun) when is_list(collection) do
_each(collection, fun)
end

defp _each([], _), do: :ok
defp _each([ head | tail ], fun) do
_each(tail, fun)
end

# filter

def filter(collection, fun) when is_list(collection) do
_filter(collection, fun, [])
end

defp _filter([], _, _), do: []
defp _filter(collection = [ head | _tail ], fun, list) do
_filter(collection, fun, list, boolean)
end
defp _filter([ head | tail ], fun, list, boolean)
when boolean === true do
[ head | _filter(tail, fun, list) ]
end
defp _filter([ _head | tail ], fun, list, _boolean) do
_filter(tail, fun, list)
end

end
``````

Took a swing, tried to do all functions without conditionals and tail call optimized where applicable.

Tested functions against the examples for each in the elixir docs 1.2-rc1.

I ended up using Enum.reverse for splitting on a negative number… Womp.

``````defmodule PragProg.Ch10.Exercises.MyList do
def take(list, 0), do: []
def take(list, count) when count > 0 do
keep
end

def take(list,count) when count < 0 do
keep
end

def split(list, count), do: _split(list,count,[])
defp _split(list, 0, acc), do: {acc, list}
defp _split([], _count, acc), do: {acc,[]}

defp _split([head|tail], count, acc) when count > 0 do
end

defp _split(list, count, acc) when count < 0 do
_rsplit(list, count, acc)
end

defp _rsplit([], _count, acc), do: {[], acc}
defp _rsplit(list, 0, acc), do: {list, acc}
defp _rsplit(list, count, acc) do
# This sucks?
[last|rest] = Enum.reverse(list)
rest = Enum.reverse(rest)
_rsplit(rest, count+1, [last|acc])
end

def filter(list, f, acc \\ [])
def filter([], _f, acc), do: acc

# Wanted to do it without and if statement
defp _filter(true, prev, list, f, acc), do: filter(list, f, acc++[prev])
defp _filter(false, _prev, list, f, acc), do: filter(list, f, acc)

def each([], _), do: :ok
each(tail,fun)
end

def all?([], _), do: true
end
# Wanted to do it without a conditional
defp _all?(_, _, false), do: false
defp _all?(list, fun, true) do
all?(list, fun)
end
end

``````

I implemented all functions to the docs so `split/2` and `take/2` allow for negative numbers as second parameter. Also, I implemented without any if statements and all are tail optimized. And, because I understood the instructions to say no using Enum I implemented my own `reverse/1` I’m curious to know if this would be considered idiomatic Elixir.

```defmodule MyEnum do
def all?(list, func \\ &(!!&1))
def all?(list, func), do: _all?(list, func, true)

defp _all?(_, _, false),           do: false
defp _all?([], _, _),              do: true
defp _all?([head | tail], func, _) do
end

def each([], _),              do: :ok
def each([head | tail], func) do
each(tail, func)
end

def filter(list, func), do: _filter(MyEnum.reverse(list), func, [], false, nil)

defp _filter([], _, selected, false, _),               do: selected
defp _filter([], _, selected, true, val),              do: [val | selected]
defp _filter([head | tail], func, selected, false, _)  do
end
defp _filter([head | tail], func, selected, true, val) do
end

def split(list, count) when count >= 0,                do: _split(list, [], count)
def split(list, count) when length(list) > abs(count), do: _split(list, [], length(list) + count)
def split(list, _),                                    do: _split(list, [], 0)

defp _split([], front, _),               do: [MyEnum.reverse(front), []]
defp _split(list, front, 0),             do: [MyEnum.reverse(front), list]
defp _split([head | tail], front, count) do
_split(tail, [head | front], count - 1)
end

def take(list, count) when count >= 0, do: split(list, count) |> hd
def take(list, count),                 do: split(list, count) |> tl |> hd

def reverse(list), do: _reverse(list, [])

defp _reverse([], reversed),            do: reversed
end
```

my full version of Enum.split function. Works with negative numbers too.

``````
defmodule Split do
def split(list, count), do: _split(list, count, 0, [])

def _split(list, count, acc, res) when acc == count do
{res, list}
end

def _split([head | tail], count, acc, res) when acc < count do
_split(tail, count, acc + 1, res ++ [head])
end

def _split([], _count, _acc, res) do
{res, []}
end

def _split(list, count, _acc, _res) when (length(list) + count) < 0 do
{[], list}
end

def _split(list, count, acc, res) when count < 0 do
_split(list, length(list) + count, acc, res)
end

end

``````

identical to split function, unfortunately not pretty concise, but works anyway, including negative numbers.

``````
defmodule Take do
def take(list, n), do: _take(list, n, 0, [])

def _take(_list, n, acc, res) when acc == n, do: res

def _take([head | tail], n, acc, res) when acc < n do
_take(tail, n, acc + 1, res ++ [head])
end

def _take([], _n, _acc, res), do: res

def _take(list, n, _acc, _res) when (length(list) + n) < 0, do: list

def _take(list, n, acc, res) when n < 0 do
list -- _take(list, length(list) + n, acc, res)
end
end

``````

With `split` inspired by Patrick’s solution

``````defmodule MyEnum do
def all?([], _), do: true

def each([], _), do: :ok
each(tail, func)
end

def filter([], _), do: []
else
filter(tail, func)
end
end

def split(list, 0), do: {[], list}
{left, right} = split(tail, count-1)
end

def take(_, 0), do: []

def flatten([]), do: []
def flatten(single), do: [single]
end
``````

For ‘split’ extended Patrick’s solution to also take negative indices.

``````defmodule MyList do
###all?
def all?(list, func), do: _all?(list, func, true)

defp _all?([], _, predicate_ans), do: predicate_ans
defp _all?([head | tail], func, _predicate_ans) do
end

###each
def each(list, func), do: _each(list, func, :ok)

defp _each([], _, ans), do: ans
defp _each([head | tail], func, _ans) do
end

###filter
def filter([], _func), do: []

def filter([head | tail], func) do
[ head | filter(tail, func) ]
else
filter(tail, func)
end
end

###split (negative indices are allowed)
def split(list, count) when count < 0 do
{right, left} = split(Enum.reverse(list), -count)
{Enum.reverse(left), Enum.reverse(right)}
end

def split([head | tail], count) when count > 0 do
{left, right} = split(tail, count-1)
end

#When count is 0
def split(list, _count), do: {[], list}

###take (negative indices are allowed)
def take(list, count) when count < 0 do
Enum.reverse take(Enum.reverse(list), -count)
end

def take([head | tail], count) when count > 0 do
end

#When count is 0
def take(_list, _count), do: []
end

###---------------------------------------
###Calling the function(s): all?
IO.puts ""
IO.puts "Calling the function(s): all?"
MyList.all?([], &(&1 < 4))  |> IO.puts
#=> true
MyList.all?([1, 2, 3], &(&1 < 4))  |> IO.puts
#=> true
MyList.all?([1, 2, 3, 4, 5], &(&1 < 4))  |> IO.puts
#=> false

IO.puts "And now using the Enum package..."
Enum.all?([], &(&1 < 4)) |> IO.puts
#=> true
Enum.all?([1, 2, 3], &(&1 < 4)) |> IO.puts
#=> true
Enum.all?([1, 2, 3, 4, 5], &(&1 < 4)) |> IO.puts
#=> false

###Calling the function(s): each
IO.puts ""
IO.puts "Calling the function(s): each"
MyList.each([], fn(x) -> IO.puts x end)
#=> ok
MyList.each(["one", "two", "three"], fn(x) -> IO.puts x end)
#=> one
#=> two
#=> three
###Using a func to double each element in the list:
MyList.each([1, 2, 3], &(IO.puts &1 * 2))
#=> 2
#=> 4
#=> 6

IO.puts "And now using the Enum package..."
Enum.each([], fn(x) -> IO.puts x end)
#=> ok
Enum.each(["one", "two", "three"], fn(x) -> IO.puts x end)
#=> one
#=> two
#=> three
###Using a func to double each element in the list:
Enum.each([1, 2, 3], &(IO.puts &1 * 2))
#=> 2
#=> 4
#=> 6

###Calling the function(s): filter
IO.puts ""
IO.puts "Calling the function(s): filter"
MyList.filter([], fn(x) -> rem(x, 2) == 0 end) |> IO.inspect
#=> []
MyList.filter([1, 2, 3], fn(x) -> rem(x, 2) == 0 end) |> IO.inspect
#=> [2]

IO.puts "And now using the Enum package..."
Enum.filter([], fn(x) -> rem(x, 2) == 0 end) |> IO.inspect
#=> []
Enum.filter([1, 2, 3], fn(x) -> rem(x, 2) == 0 end) |> IO.inspect
#=> [2]

###Calling the function(s): split
IO.puts ""
IO.puts "Calling the function(s): split"
MyList.split([], 3)  |> IO.inspect
#=> {[], []}
MyList.split([1, 2, 3, 4, 5], 2) |> IO.inspect
#=> {[1, 2], [3, 4, 5]}
MyList.split([1, 2, 3, 4, 5], 3) |> IO.inspect
#=> {[1, 2, 3], [4, 5]}

#If 'count' is negative: starts counting from end
#(ie 5 shown here) to beginning.
MyList.split([1, 2, 3, 4, 5], -2) |> IO.inspect
#=> {[1, 2, 3], [4, 5]}
MyList.split([1, 2, 3, 4, 5], -3) |> IO.inspect
#=> {[1, 2], [3, 4, 5]}
MyList.split([1, 2, 3, 4, 5], -4) |> IO.inspect
#=> {[1], [2, 3, 4, 5]}
MyList.split([1, 2, 3, 4, 5], -5) |> IO.inspect
#=> {[], [1, 2, 3, 4, 5]}
MyList.split([1, 2, 3, 4, 5], -10) |> IO.inspect
#=> {[], [1, 2, 3, 4, 5]}
MyList.split([1, 2, 3, 4, 5], 0) |> IO.inspect
#=>{[], [1, 2, 3, 4, 5]}

IO.puts "And now using the Enum package..."
Enum.split([], 3) |> IO.inspect
#=> {[], []}
Enum.split([1, 2, 3, 4, 5], 2) |> IO.inspect
#=> {[1, 2], [3, 4, 5]}
Enum.split([1, 2, 3, 4, 5], 3) |> IO.inspect
#=> {[1, 2, 3], [4, 5]}
Enum.split([1, 2, 3, 4, 5], -2) |> IO.inspect
#=> {[1, 2, 3], [4, 5]}
Enum.split([1, 2, 3, 4, 5], -3) |> IO.inspect
#=> {[1, 2], [3, 4, 5]}
Enum.split([1, 2, 3, 4, 5], -4) |> IO.inspect
#=> {[1], [2, 3, 4, 5]}
Enum.split([1, 2, 3, 4, 5], -5) |> IO.inspect
#=> {[], [1, 2, 3, 4, 5]}
Enum.split([1, 2, 3, 4, 5], -10) |> IO.inspect
#=> {[], [1, 2, 3, 4, 5]}
Enum.split([1, 2, 3, 4, 5], 0) |> IO.inspect
#=>{[], [1, 2, 3, 4, 5]}

###Calling the function(s): take (negative indices are allowed)
IO.puts ""
IO.puts "Calling the function(s): take"
MyList.take([1, 2, 3, 4, 5], 0) |> IO.inspect
#=> []
MyList.take([1, 2, 3, 4, 5], 1) |> IO.inspect
#=> [1]
MyList.take([1, 2, 3, 4, 5], 2) |> IO.inspect
#=> [1, 2]
MyList.take([1, 2, 3, 4, 5], 5) |> IO.inspect
#=> [1, 2, 3, 4, 5]
MyList.take([1, 2, 3, 4, 5], -1) |> IO.inspect
#=> [5]
MyList.take([1, 2, 3, 4, 5], -2) |> IO.inspect
#=> [4, 5]

IO.puts "And now using the Enum package..."
Enum.take([1, 2, 3, 4, 5], 0) |> IO.inspect
#=> []
Enum.take([1, 2, 3, 4, 5], 1) |> IO.inspect
#=> [1]
Enum.take([1, 2, 3, 4, 5], 2) |> IO.inspect
#=> [1, 2]
Enum.take([1, 2, 3, 4, 5], 5) |> IO.inspect
#=> [1, 2, 3, 4, 5]
Enum.take([1, 2, 3, 4, 5], -1) |> IO.inspect
#=> [5]
Enum.take([1, 2, 3, 4, 5], -2) |> IO.inspect
#=> [4, 5]

``````

My implementation:

```defmodule MyEnum do
def all?([], _), do: true
all?(tail, func)
else
false
end
end

def each([], _), do: []
end

def filter([], _), do: []
else
filter(tail, func)
end
end

def take([], _), do: []
def take(_, 0), do: []
end

def split(list, index), do: _split([], list, index)
end
```

My split implementation differs from the author and avoids a reverse. Is there any disadvantage to using the list concatenation? Also, the exercise states we can’t use any library functions.

```defmodule En do
def all?(enum), do: all?(enum, &(&1))
def all?([], _fun), do: true
def all?([head | tail], fun) do
end

def each([], _fun), do: :ok
def each([head | tail], fun) do
each(tail, fun)
end

def filter([], _fun), do: []
def filter([head | tail], fun) do
else
filter(tail, fun)
end
end
end
```
``````defmodule MyLists do

def fold([], v, _), do: v
def fold([h|t], v, f), do: fold(t, f.(v, h), f)

def reverse(l), do: fold(l, [], &([&2|&1]))

def all?([], _), do: true
def all?([h | t], f), do: f.(h) and all?(t, f)

def each([], _), do: :ok
def each([h | t], f) do f.(h); each(t, f) end

def filter(l, f), do: fold(l, [], &(if f.(&2) do [&2|&1] else &1 end))

def split(l, n) when is_integer(n) and n >= 0 do _split(l, n, []) end
def split(l, n) when is_integer(n) and n < 0 do _split_r(reverse(l), -n, []) end

defp _split(l, n, c) when n == 0 or l == [] do {reverse(c), l} end
defp _split([h|t], n, c) when n > 0 do _split(t, n - 1, [h|c]) end

defp _split_r(l, n, c) when n == 0 or l == [] do {reverse(l), c} end
defp _split_r([h|t], n, c) when n > 0 do _split_r(t, n - 1, [h|c]) end

def take(l, 0) when is_list(l) do [] end
def take([], n) when is_integer(n) and n > 0 do [] end
def take([h|t], n) do [h|take(t, n - 1)] end

end
``````
```defmodule MyEnum do
def all?([],_func), do: true

def each([],_func), do: []

def filter([], _func), do: []
else
filter(tail, func)
end
end

def split(list, count) when count > 0, do: _split(list, [], count)
def split(list, count), do: _split(list,[],(Enum.count(list) + count))
defp _split([], front, _), do: {Enum.reverse(front),[]}
defp _split(tail, front, 0) , do: {Enum.reverse(front), tail}

def take(list, count) when count < 0, do: Enum.reverse take(Enum.reverse(list), -count)
def take(_list, 0), do: []
else
end
end
end
```
``````defmodule MyList do
def splitdo(list, pos) do
{handle(list,pos), list -- handle(list,pos)}
end

def handle([], pos), do: []
def handle([head | tail], pos) when (pos > 0) do
end
def handle(list, pos) when (pos < 0) do
if (length(list) + pos > 0) do
newpos = length(list) + pos
handle(list, newpos)
else
handle(list,0)
end
end
def handle(_, pos) when (pos == 0) do
[]
end
end
``````

My version of `each` function:

```defmodule MyList do
def each([], _fun), do: :ok
def each([ head | tail ], fun) do
each(tail, fun)
end
end
```
``````defmodule Enumerate do
def map([], _func), do: []

def all?([one], func), do: func.(one)
def all?([head | tail], func) do
end

def each([], _func), do: :ok
def each([head | tail], func) do
each(tail, func)
end

def filter([], _func), do: []
def filter([ head | tail], func) do
else
filter(tail, func)
end
end

def split(list, 0), do: list
def split( list, index) do
takesome = take(list,index)
[ takesome | [list -- takesome] ]
end

def take(_list, 0), do: []
def take( [head | tail], index ) do
end

#only nests so far....

def flatten([]), do: []
def flatten([elem | tail]) when is_list(elem) == false, do: [elem | flatten(tail)]

end
``````
``````defmodule MyEnum do
def all?([], fun), do: true
def all?([head | tail], fun) do
all?(tail, fun)
else
false
end
end

def each([], _), do: []
def each([head  | tail], fun) do
end

def filter([], _), do: []
def filter([head | tail], fun) do
else
filter(tail, fun)
end
end

def split(list, position) do
{_split(list, position, 0), Enum.reverse _split(Enum.reverse(list), position - 1, 0)}
end

defp _split([head | tail], position, count)
when count < position do
[head | _split(tail, position, count + 1)]
end

defp _split(_, _, _), do: []

def take(list, num) do
_take(list, num, 0)
end

defp _take([head | tail], num, count)
when count < num do
[head | _take(tail, num, count + 1)]
end

defp _take(_, _, _), do: []

def flatten([]), do: []

end

end

end
``````

Took me a while to figure out the default function arguments.

```defmodule MyEnum do

def all?(l, f \\ &(not ! &1))
def all?([], _), do: true
def all?([h | t], f) do
if f.(h),
do: all?(t, f),
else: false
end

def each([],_), do: :ok
def each([h|t],f) do
f.(h)
each(t, f)
end

def filter([], _), do: []
def filter([h|t], f) do
if f.(h),
do: [h | filter(t,f)],
else: filter(t,f)
end

defp _split([], {l1, l2}, _), do: {Enum.reverse(l1), Enum.reverse(l2)}
defp _split([h|t],{l1, l2}, n) when n > 0 do
_split(t, {[h|l1], l2}, n - 1)
end
defp _split([h|t],{l1, l2}, n), do: _split(t, {l1, [h|l2]}, n - 1)

def split(l, n), do: _split(l, {[],[]}, n)

defp _take([], lr, _), do: Enum.reverse(lr)
defp _take(_, lr, 0), do: Enum.reverse(lr)
defp _take([h|t], lr, n), do: _take(t, [h|lr], n - 1)
def take(l, n), do: _take(l,[], n)

def map([], _), do: []
def map([h|t], f), do: [f.(h) | map(t,f)]
end
```

List concatenation operator (`++`) helps a lot. Also, take and split can take negative numbers and split/take from the end of list. Used built-in `length` function with some helpers to handle this.

```defmodule MyList do

def all?(enumerable, fun \\ fn x -> x end)
def all?([], _fun), do: true

def each([], _fun), do: :ok
def each([head | tail], fun) do
each(tail, fun)
end

def filter([], _fun), do: []
def filter([head | tail], fun) do
else
filter(tail, fun)
end
end

def split(enumerable, count) when count < -length(enumerable), do: {[], enumerable}
def split(enumerable, count) when count > length(enumerable), do: {enumerable, []}
def split(enumerable, count) when count < 0, do: _split([], enumerable, length(enumerable) + count)
def split(enumerable, count), do: _split([], enumerable, count)

defp _split(taken, remainder, 0), do: { taken, remainder }
defp _split(taken, [], _count), do: { taken, [] }
defp _split(taken, [head | tail], count), do: _split(taken ++ [head], tail, count - 1)

def take(enumerable, count) when not count in -length(enumerable)..length(enumerable), do: enumerable
def take(enumerable, count) when count < 0, do: _drop(enumerable, length(enumerable) + count)
def take([], _count), do: []
def take(_enumerable, 0), do: []
def take([head | tail], count), do: [head | take(tail, count - 1)]

defp _drop([], _count), do: []
defp _drop(what_remains, 0), do: what_remains
defp _drop([head | tail], count), do: _drop(tail, count - 1)

end
```

I handled negative offsets for ‘split’ a little differently. I hand-rolled a cut-rate ‘length’ function, then used that to convert negative offsets to positive.

``` def split([],_), do: {[],[]}
def split([h|t], n), do:
_split({[], [h|t]}, n)
defp _split({l1,l2}, 0), do: {l1,l2}
defp _split({l1,[]},_), do: {l1,[]}
defp _split({l1,l2}, n) when n < 0, do:
_split({l1,l2}, _norm(_len(0,l2),n))
defp _split({l1,[h|t]}, n), do:
_split({l1++[h], t}, n-1)

defp _len(count,[]), do: count
defp _len(count,[_h|t]), do:
_len(count+1,t)
defp _norm(len, n) when len + n < 0, do: 0
defp _norm(len, n), do: len + n
```

Filter without if

defmodule MyList do

``````# all? function

def all?(x, func1 \\ &(&1) , state \\ true)

def all?(x, func1, state) when ( x == [] or state == false ) do
state
end

def all?([head|tail], func1, state) when state == true do
end

#filter
def filter(x,funct1 \\ &(&1), state \\ true, init \\ 0)

def filter([a|[b|tail]],funct1,state,init) when init == 0 do
filter([a|[b|tail]],funct1,funct1.(a),1)
end

def filter([],funct1,state,init), do: []

def filter([x|[]], funct1, state, 1) when state == false do
filter([], funct1, state, 1)
end

def filter([x|[]], funct1, state, 1) when state == true do
[x | filter([],funct1,state,1)]
end

def filter([a|[b|tail]],funct1,state,init) when (state == true and init != 0) do
[a | filter([b|tail],funct1,funct1.(b),1)]
end

def filter([a|[b|tail]], funct1,state,init) when (state== false and init != 0) do
filter([b|tail],funct1,funct1.(b),1)
end

#Split
def split([]), do: [];
def split([a,b|[]]), do: [[a,b]|split([])]
def split([a|[]]), do: [[a]|split([])]
def split([a,b,c|tail]), do: [[a,b,c]|split(tail)]

#take
def take(x,c,init \\0) when (init>=c or x==[]) do
[]
end
def take([a|tail],c,init), do: [a|take(tail,c,init+1)]
``````

end

the all? Is it Elixirish to write as this?

``````	def all?(list), do: all?(list, & !!&1)
def all?([], fun), do: true
``````

Here was my approach. I did not use any library functions. I wanted to be as clear as possible so I broke up every possible logical process.

``````
defmodule MyEnum do

# all?
def all?(list), do: all?(list, fn x-> !!x end) # !! converts to truthy 'true'
def all?([], _func), do: true
def all?([head | tail], func) do
all?(tail, func)
else
false
end
end

# each
def each([], _func), do: []

# filter
def filter([], accum, _func), do: accum
def filter([head | tail], accum, func) do
else
filter(tail, accum, func)
end
end

# split
def split(list, count) do
cond do
count < 0 && abs(count) > length(list) ->
_split_negative(list, [], list, abs(count))
count < 0 ->
_split_negative(reverse(list), [], list, abs(count))
count >= 0 ->
_split(list, [], list, count)
end
end

#defp _split_negative(list, taken, remaining, count)
#  when length(list) == 0 or count == 0, do: {remaining, taken}

defp _split(list, taken, remaining, count) do
cond do
# base case
length(list) == 0 || count == 0 ->
{taken, remaining}
count >= 0 ->
end
end

defp _split_negative(list, taken, remaining, count) do
cond do
# base case
length(list) == 0 || count == 0 ->
{remaining, taken}
count >= 0 ->
end
end

# take
def take(list, count) do
if (count < 0) do
_take(reverse(list), [], list, abs(count))
else
_take(list, [], list, count)
end
end

# base case - when list is empty or count = 0, return empty list
defp _take(list, taken, _, count)
when length(list) == 0 or count == 0, do: taken

defp _take(list, taken, remaining, count) do
end

# reverse
def reverse(list), do: _reverse(list)
defp _reverse([]), do: []
defp _reverse(list) do
reduce(list, [], fn (x, acc) -> [x | acc] end)
end

# reduce
def reduce([], value, _), do: value
def reduce([head | tail], value, func) do