fun({0, M}) -> {M+1, M-2};
fun({N, M}) ->
{A, B} = fun({N-1, M+1}),
{B, A+1}.
so I am kinda unsure of what the A and B would be and how the next recursive call would be. let say 2,2
so it would be
f(2,2) -> {A,B} = fun({1,3}), {B,A+1}
f(1,3) -> {A,B} = fun({0,4}), {B,A+1}
f(0,4) -> {5,2}
but where does A and B go and do they change in each recursive call?
As a very basic explanation of "where is my variable", consider the countdown function in this example module:
-module(example).
-export([countdown/1]).
-spec countdown(non_neg_integer()) -> ok.
countdown(0) ->
io:format("Blastoff!~n");
countdown(N) when N > 0 ->
ok = io:format("Counting down in: ~w~n", [N]),
Next = N - 1,
countdown(Next).
If we hit the base case, which is 0
, then we stop. The return value of the function overall is the atom ok
(because that is the return value of a successful call to io:format/2
).
If the input is greater than 0
then we match on the second clause, which means we assign N
the sole input argument for this particular iteration. The next thing we do is make our output call. Then we assign Next
to the value N - 1
. Then we call the same function again (do a loop) using the value of Next
in body of the the current call as the input argument.
The next iteration all the variables are totally new because this is a fresh execution context. The old N
and Next
no longer exist. In fact, they don't event exist on a stack anywhere because Erlang uses "tail call optimization" to maintain recursive tail calls in constant space, the same way most other languages would do an explicit for
or while
or do while
or [insert form].
As Alexy points out, be careful about the token fun
-- it is a keyword in Erlang, not a legal function name. It is the non-name of an anonymous function (also known as a lambda). In other words, unless you provide a label, the name of every anonymous function is just fun
.
fun
is also the keyword that is used to reference a function by label (to use as a value itself) instead of calling it. For example, countdown(10)
calls the function above with an argument of 10
. Referencing the function as fun countdown/1
returns the function itself as a value. That is, incidentally, why the function export declaration at the top of the module is written as -module([countdown/1])
, because that is the explicit name of this function. Consider this:
1> c(example).
{ok,example}
2> example:countdown(2).
Counting down in: 2
Counting down in: 1
Blastoff!
ok
3> Countdown = fun example:countdown/1.
#Fun<example.countdown.1>
4> Countdown(2).
Counting down in: 2
Counting down in: 1
Blastoff!
ok
While I'm on the subject...
Erlang has very few keywords compared to most languages (and very little syntax, actually). Here is the list of reserved words:
after and andalso band begin bnot bor bsl bsr bxor case catch cond div end fun if let not of or orelse receive rem try when xor
You just need to go back up:
f({1, 3}) -> {A, B} = {5, 2}, {B, A+1} -> {2, 6}
f({2, 2}) -> {A, B} = {2, 6}, {B, A+1} -> {6, 3}
(note that fun
is a keyword in Erlang and that f(N,M)
is not the same as f({N,M})
)
and do they change in each recursive call
Yes, as you can see.