views:

102

answers:

5

I am trying to return the max of a list.

I have the following code

list_max([]) ->
    [];
list_max([H|T]) ->
    list_max(H, T).
list_max(Temp, []) ->
    Temp;
list_max(Temp, [H|T]) when H > Temp ->
    Temp = H;
list_max(Temp, T).

But am struggling to relate to Erlang.

How do I assign something to temp and replace it to the highest?

+2  A: 

Erlang is one of those languages in which I find it easier to show than to explain.

list_max([]   ) -> empty;
list_max([H|T]) -> {ok, list_max(H, T)}.

list_max(X, []   )            -> X;
list_max(X, [H|T]) when X < H -> list_max(H, T);
list_max(X, [_|T])            -> list_max(X, T).

and call it thus:

{ok, Max} = list_max(MyList).
Marcelo Cantos
+2  A: 

You can also express than in built in functions:

-module(list_max).
-compile(export_all).

list_max([]) -> none;
list_max([H | T] = List) ->
    lists:foldl(fun erlang:max/2, H, T);
list_max(_) -> badarg.
stmi
Since `max` is associative, you should use the tail-recursive `foldl` instead.
Marcelo Cantos
That is way to much for me to take in but thank you. Just started doing erlang this term in Uni.
alJaree
@Marcel Cantos You're right. I'll correct that.
stmi
`when is_list(List)` is almost useless here because it only check if there is `[]` or [_|_]. It doesn't check "proper list".
Hynek -Pichi- Vychodil
@Hynek Well... it is not almost useless... it is *completely* useless because the matching on a list (using angle brackets) already tells you that it is a list.
Mazen Harake
indeed "when" clause was completely useless, so acting on popular demand I've corrected this too.
stmi
+2  A: 

How do I assign something to temp and replace it to the highest?

The short answer is that you can't. Variables in Erlang cannot be changed once assigned.

The slightly longer answer is that, while you can't change a variable inside a particular function call, you can always self-recurse. Tail-recursion in Erlang is optimized.

In the example code that you provided, list_max will only ever look at the first two elements of the list. The fourth and fifth clauses should each call list_max again, with the new value of Temp in the first parameter. This is a common thing to do in functional languages. In this case, Temp is known as an Accumulator (I often name the variable Acc to reflect this use, but of course you can name it whatever you want).

Let me show another solution that could be seen as "in between" Macelo's answer and stmi's answer:

list_max( [H|T] ) -> list_max( H , T ).

list_max( X , []    ) -> X;
list_max( X , [H|T] ) -> list_max( erlang:max(H, X) , T ).

(I also ditched the clause that detects the empty list, because I don't think it really buys you much - though it will now throw an exception if you call it with an empty list.)

Daniel Yankowsky
A: 

Erlang is a single assignment so you cannot change "variables". You can only create new ones.

My recommendation is to look at the lists module. Inside lists.erl you will find:

max([H|T]) -> max(T, H).

max([H|T], Max) when H > Max -> max(T, H);
max([_|T], Max)              -> max(T, Max);
max([],    Max)              -> Max.

You don't update the Max variable (Temp in your example), but rather call the function with the new value or return it from the function.

Easy peasy... :-)

Daniel Luna
A: 

Sorry, maybe I'm missing something. Are you looking for:

lists:max(List). %% Find the max in List
Mazen Harake
No, I need to do it myself. :P
alJaree