5

Given a function:

min(A, B)  when A =< B -> A;
min(_A, B)             -> B.

can I use this in the function foldlin a similar fashion to this:

lists:foldl(fun min/2, 0, [1,2,3,4,5,6,7,8,9,10])

I believe it is not possible, because I have to set an initial value that will be compared to the rest of the list, e. g. there is no identity function that I can think of. Am I right?

Syntax is written in Erlang, but should be readable for non Erlang programmers, too.

YasirA
  • 9,531
  • 2
  • 40
  • 61
Magnus Kronqvist
  • 1,559
  • 12
  • 22

3 Answers3

11
min(List) ->
    Min = fun(A,  B) when A < B -> A;
             (_A, B)            -> B end,
    lists:foldl(Min, undefined, List).

Using undefined as the initial state should do the trick. Returns undefined for an empty list, which is kind of nice as an API.

If you want it to crash on an empty list, use this function header instead:

min([Head|Rest]) ->
    Min = fun(A,  B) when A < B -> A;
             (_A, B)            -> B end,
    lists:foldl(Min, Head, Rest).
Adam Lindberg
  • 16,447
  • 6
  • 65
  • 85
  • Good answer! Seems even like the first guard (undefined,B) -> B is redundant. – Magnus Kronqvist Mar 02 '11 at 13:52
  • Actually just out randomness it does not crash. I don't know if the result is deterministic, but out of the examples I have tried with, a comparison of any number and atom returns the number as being smaller. – Magnus Kronqvist Mar 02 '11 at 14:03
  • 3
    Passing `undefined` works because there is a well-defined order for the `<` operator when working with heterogenous types. In particular, Numbers are always less than atoms. Look up the order functions in the reference manual. – I GIVE CRAP ANSWERS Mar 02 '11 at 16:10
5
1> List = [42,13,25,3,19,20].
[42,13,25,3,19,20]
2> lists:foldl(fun(X, Y) -> erlang:min(X,Y) end, hd(List), tl(List)).   
3

Crashes a program on an empty list, a recommended approach "let it crash" as opposed to defensive programming.

Peer Stritzinger
  • 8,232
  • 2
  • 30
  • 43
YasirA
  • 9,531
  • 2
  • 40
  • 61
  • Oops, the last argument to the `foldl` should be `tl(List)` (the list tail). I wish we had the function `foldl1` which is found in Haskell, so that we don't use the initial value. – YasirA Mar 02 '11 at 13:55
2

Adam Lindbergs proposal to use undefined as initial value has the disadvantage that it generates weird results for lists that has atoms as members. Erlang has a global ordering of all objects, so a nice property of a min function would be to be usable for all types.

I think its more reasonable to crash on an empty list. The difference is that the client has to worry about the case, instead of having to worry about getting a undefined as the result.

Lii
  • 11,553
  • 8
  • 64
  • 88