Reputation: 995
Erlang noob here, I have a function which takes any number and breaks it down to separate digits in a list. Ex, 654 -> [6, 5, 4]
My code is as follows
digitize(X) when X > 0 ->
[digitize(X div 10)| (X rem 10)];
digitize(0) ->
[].
However the return is odd. FOr the input 654, the return will be: [[[[]|6]|5]|4]. What is wrong with my code?
Upvotes: 1
Views: 139
Reputation: 3584
In short, you are returning too much lists :)
Sometimes when designing recursions, it is easier to thing about them from the end. This could make more sense, since it is the way the stack unwinds. So lets try to break down your example.
digitize
is called with 0
. In that case it returns empty list []
.digitize
was called with 6
(with sustituted[digitize(6 div 10)| (6 rem 10)];
) when this empty list becomes head of list, (after substitution [ [] | 6];
, which is returned to next level.65
where again return value is created by [ [] | 6];
as head, and (65 rem 10)
as tail. So again, we have list, which first element (head) is list, and second (tail) is one number (from rem
)Hope you see the problem. Now lets try to find a solution, lets describe your algorithm. On each level of recursion you basically add (X rem 10)
, which is "smallest digit in X" to list of greater digits (recursion). Or to speak in programming terms, you append to list. The problem is that head-tailing is more like putting/poping from beginning, where Head is one element and Tail is a list. Fortunately there is lists:append/2
function, or even syntactic sugar that allows to add two list:
digitize(X) when X > 0 ->
digitize(X div 10) ++ [X rem 10];
digitize(0) ->
[].
And this works just fine.
Those are not really a problems, but we could improve on lack of tail recursion, and ++
operator which can be much less efficient than [H | T]
. So we could invest little more effort in our function, and rewrite it like this:
digitize(Int) ->
lists:reverse(digitize(Int, _Acc = []).
digitize(Int, Acc) when X > 0 ->
digitize(X div 10, [(X rem 10) | Acc]);
digitize(0, Acc) ->
Acc.
I would encourage you to investigate this code more, even if previous version is enough. Try to understand why this could be faster, why can we use head-tail, and why do we have to reverse list at the end. http://learnyousomeerlang.com/recursion is great start. Good luck!
Upvotes: 8