concept not sinking in. tail recursion.

[Term | List] means "The list List but with Term added to the head".

Let us first be clear on what the functions are meant to do: tail_duplicate should give you a list consisting of Term repeated N times. So tail_duplicate(4, foo) = [foo, foo, foo, foo]

Let us call the three formulas for a, b, and c.

a:

tail_duplicate(N, Term) ->
tail_duplicate(N, Term, []).

b:

tail_duplicate(0,_,List)->
List;

c:

tail_duplicate(N, Term, List) when N > 0 ->
tail_duplicate(N-1, Term, [Term|List]).

So a will create an empty list to store the duplicates, c will add Term to the front of the list and decrement N of N>0, and b just tells the function to return the list when N is 0.

So tail_duplicate(4, foo) = tail_duplicate(4, foo, []) //by a = tail_duplicate(3, foo, [foo]) //by c = tail_duplicate(2, foo, [foo, foo]) //by c = tail_duplicate(1, foo, [foo, foo, foo]) //by c = tail_duplicate(0, foo, [foo, foo, foo, foo]) //by c = [foo, foo, foo, foo] //by b

Now, the thing about tail recursion is that if the very last thing a function does is to call another function (or itself recursively), then state of the calling function is no longer needed once the other function has been called.

A different way of writing the duplicate function would be

duplicate(0, Term) -> 
  [];
duplicate(N, Term) when N > 0 -> 
  [Term | duplicate(N-1, Term)].

This code does the same thing, but it can not benefit from tail recursion (unless the compiler is clever, which it might be). The problem is that duplicate(N, Term) must wait for duplicate(N-1, Term) to be evaluated, so that it can add another Term entry to the front of the list.

Tail recursion can be explained by imagining a general standing in front of a line of N soldiers and wants to know how many soldiers there are, so he asks the soldier to the left how many they are.

The straight-forward way would be for the soldier to ask the soldier to the right how many him and all the people to his right are. That soldier will then ask the soldier to his right how many that soldier and all the soldier to his right are, etc. until the rightmost soldier reports that it is just him (1). The soldier to the left of him will then add 1 to this number to include himself and report to the soldier to the left of him again that they are 2 soldiers, etc. Eventually the soldier to the left will hear that there are N-1 soldiers to the right of him, so he will add 1 and report to the general that there are N soldiers.

The tail-recursive way would be for the leftmost soldier to say "the general wants to know how many we are. We are 1 (just me) so far" to the soldier to his right. That soldier will then say "the general wants to know how many we are. We are 2 so far." etc. until the rightmost soldier hears "the general wants to know how many we are. We are N-1 so far." who will then report directly to the general that they are N people.

/r/erlang Thread