for simplicity sake I am assuming that the input is always a non empty list. This is my non functioning implementation of the function:
def max([a]), do: a
def max([head | tail]), do: reduce([head | [second | tail]], check_big(head,second), check_big)
def check_big(a,b) when a > b, do: a
def check_big(a,b) when a <= b, do: b
When I try to compile the file I get this error message:
Mylist.ex:15: undefined function check_big/0
why can’t I just pass a reference to the function? why isn’t it working?
def max([a]), do: a
def max([head | tail]), do: reduce(tail, head, &check_big/2)
def check_big(a,b) when a > b, do: a
def check_big(a,b) when a <= b, do: b
It is totally fine to assume that there will be at least one element in the list, as there is no maximum defined for the empty list (this is also true for minimum).
There are two ways in elixir to solve this. One is to just let it crash, though this way you take the opportunity to handle the problem from the caller.
The other is, to return an ok/error tuple.
Also you really do not need to special case the singleton list. as reduce/3 with an empty list will just return the accumulator.
Next is that I’d call your current check_big/2max/2 instead, as this is the name it is known as and taught in match classes.
Last but not least I’d probably implement that max/2 as a single clause with an if/2, or at least drop the second guard.
Although, this is not the best solution to find greatest value in a list. However, in the book Programming Elixir 1.6, the quiz was supposed to be solved by implementing a reduce function, called max, with the help of recursion, pipe operator, anonymous function, comparison operators, guard clauses and pattern matching only. Without using any other predefined module/library functions or control flow constructs, if, unless, case etc.
Here is another version I wrote using Relaxed Boolean Operators (II and &&) to find greater of two numbers.
########### Find Greatest Value within a List - V2.0 ##########
def max([], val, _func), do: val
def max([head | tail], val , func), do: max(tail, func.(head, val), func)
def max(list), do: max(list, 0, fn a,b -> a >= b && a || b end)
I know you arrived at a different solution, but for learning purposes, your error is caused by the fact that naming a function w/out parens still calls it as if empty params were provided– aka check_big().
The way to get a function reference of a named function is to use the capture operator, &. aka &check_big/0 to pass it around!