Here the simplest recursive function over list type. This function only navigate into a list from its start to its end and do nothing more.
-spec loop(list()) -> ok.
loop([]) ->
ok;
loop([H|T]) ->
loop(T).
You can call it like this:
loop([1,2,3]). % will return ok.
Here the recursive function expansion:
loop([1|2,3]) ->
loop([2|3]) ->
loop([3|]) ->
loop([]) ->
ok.
Previous code do nothing, and is pretty useless. So, we will create now a recursive function who execute some actions. This code is similar to lists:foreach/2
.
-spec loop(list(), fun()) -> ok.
loop([], _) ->
ok;
loop([H|T], Fun)
when is_function(Fun) ->
Fun(H),
loop(T, Fun).
You can call it in like this:
Fun = fun(X) -> io:format("~p", [X]) end.
loop([1,2,3]).
Here the recursive function expansion:
loop([1|2,3], Fun(1)) ->
loop([2|3], Fun(2)) ->
loop([3|], Fun(3)) ->
loop([], _) ->
ok.
You can compare with lists:foreach/2
output:
lists:foreach(Fun, [1,2,3]).
Another useful example, similar to lists:map/2
. This function will take one list and one anonymous function. Each time a value in list is matched, we apply function on it.
-spec loop(A :: list(), fun()) -> list().
loop(List, Fun)
when is_list(List), is_function(Fun) ->
loop(List, Fun, []).
-spec loop(list(), fun(), list()) -> list() | {error, list()}.
loop([], _, Buffer)
when is_list(Buffer) ->
lists:reverse(Buffer);
loop([H|T], Fun, Buffer)
when is_function(Fun), is_list(Buffer) ->
BufferReturn = [Fun(H)] ++ Buffer,
loop(T, Fun, BufferReturn).
You can call it like this:
Fun(X) -> X+1 end.
loop([1,2,3], Fun).
Here the recursive function expansion:
loop([1|2,3], Fun(1), [2]) ->
loop([2|3], Fun(2), [3,2]) ->
loop([3|], Fun(3), [4,3,2]) ->
loop([], _, [4,3,2]) ->
list:reverse([4,3,2]) ->
[2,3,4].
This function is also called "tail recursive function", because we use a variable like an accumulator to pass modified data over multiple execution context.