Playing with recursion, (Learning Erlang 6).
Published on Apr 08, 2012Other articles in the Learning Erlang series.
- Learning Erlang.
- Heads and tails, working with lists. (Learning Erlang 2)
- Variables, comparisons and dynamic typing. (Learning Erlang 3)
- Modules and functions, Erlang building blocks (Learning Erlang 4).
- Module attributes and compilation (Learning Erlang 5).
- Playing with the file module (part 1). (Learning Erlang 7)
- The file module (part 2). (Learning Erlang 8)
- String manipulation in Erlang. (Learning Erlang 9)
- Records. (Learning Erlang 10)
- Functional arrays. (Learning Erlang 11)
Note of caution. These are my notes while learning Erlang. You are welcome to follow along and use them as a guide. Please make sure to check the Erlang language site
In Erlang you utilize recursion instead of loops. It used to be very important to utilize Tail recursive functions for performance considerations and to not blow the stack. In recent versions of the language this is not necessarily the case. Refer to the article The Eight Myths of Erlang Performance for more information on the subject.
Tail recursion
A tail recursive function is one where the last statement is a call to itself.
Let’s create a simple function that calculate fees on an amount and return a Tuple with the original amount and the sum of the fees to be paid. (The math makes no sense in this example but we don’t care about the business case here)
So, we create a recursion module and we export only one function, calculateFees\2
The client calls calculateFees\2 and internally we call calculateFees\3
While the list is not empty It will match the second head for calculateFees\3.
Notice what’s is going on in here, on each call we take the head from the list and calculate the fees based on the amount. Then we call ourselves calculateFees\3, passing the tail in the second position. Once the list is empty we will match against the first head of the function.
At this point we return a tuple with the original amount and the calculated fees.
<aside class=“resources”>
Links
</aside>
No case to match.
If you forget to add a clause for a given case, your code will throw an exception on runtime. Ex, in this case we forgot to add a case to handle an empty list.
Infinite loops
This example is extremely silly, but this same issue can happen with more complicate code.
We have a guard clause but in the recursive call we are always adding a new element to the list (in this case is just the same list).
A slight variation of the code is when we don’t use tail recursion but body recursion and may eventually blow the stack.
I run the code above for a good 20 minutes in my old laptop without blowing it. So again, check The Eight Myths of Erlang Performance for more information.