defmodule MyEnum do # all?/1 # Returns true if all elements in enumerable are truthy. def all?([head | tail]) do # head truthy and all tail head != false and head != nil and all?(tail) all?([head | tail], fn elem -> elem != false and elem != nil end) end def all?([]) do all?([], nil) end def all?([head | tail], fun) do fun.(head) and all?(tail, fun) end def all?([], _fun) do true end # each/2 # Invokes the given fun for each element in the enumerable. def each([head | tail], fun) do fun.(head) each(tail, fun) end def each([], _fun) do :ok end # Filters the enumerable, i.e. returns only those elements for which fun returns a truthy value. def filter([], _fun) do # do nothing -> This is wrong. Return an empty array instead. [] end # filter using if ... do ... else ... end def filter([head | tail], fun) do if fun.(head) do [head | filter(tail, fun)] else filter(tail, fun) end end # I gave up on these two. # split # take end defmodule MyList do def flatten([]) do [] end def flatten([head | tail]) do # this is basically the recursion flatten(head) ++ flatten(tail) end def flatten(head) do # if there's only on element, we make a list out of it, so that we can concat them [head] end end defmodule MyStream do def squared(n), do: n * n def iterate() do # Stream.iterate/2 takes a start value x and a function f # It then applies the function to the start value. And then it applies the function to f(x). And # then to f(f(x)) until it stops. # squared = fn n -> n*n end Stream.iterate(2, &squared/1) # How can I use a named function here? -> Use a &name/arity |> Enum.take(5) end def fibonacci_unfold({f1, f2}) do # first return-value of the tuple is the calculated state, second value is the next input {f1, {f2, f1 + f2}} end def unfold() do # more general, but related to iterate # Each value is some function of the previous state. # You calculate this rounds result and provide the next value # function is of form: # fn state -> {stream_value, new_state} seed = {0, 1} Stream.unfold(seed, &fibonacci_unfold/1) |> Enum.take(15) end def read_lines(number_of_lines) do start_fun = fn -> File.open!("/Users/nathan/tmp/text.ex") end next_fun = fn file -> case IO.read(file, :line) do data when is_binary(data) -> {[data], file} _ -> {:halt, file} end end after_fun = fn file -> File.close(file) end Stream.resource(start_fun, next_fun, after_fun) |> Enum.take(number_of_lines) |> IO.puts() # Stream.resource/3 is useful to stream values from resources (files, time, etc.) end end defmodule Countdown do def sleep(seconds) do receive do after seconds * 1000 -> nil end end def next(0) do # looks at the time left {:halt, 0} end def next(n) do # sleep for a second sleep(1) {[inspect(n)], n-1} end def start() do {_h, _m, s} = :erlang.time # why is this nil???? This method was never invoked as I had defined it twice (there was a warning but I ignored it.) 60 - s - 1 end def timer do Stream.resource(&start/0, &next/1, fn _ -> nil end) end end