Like many, I started out with procedural programming. Of course, when learning a functional language, old habits may die hard, so I wrote a fairly trivial little thing which takes an integer and returns a list of the english-language representation.
A few days later, I re-wrote it to try to take advantage of tail recursion in the main order-of-magnitude function; I freely admit that no attempt has been made to add tail-recursion to the calculation of numbers less than 1000, but since those have a fixed maximum depth of 3 (and a maximum of 5 calls in any case) I opted not to worry about it for now.
Any notes and criticisms, please lob them at me, that I may learn to do things in a less procedural way.
-module(titoa).
-export([itoa/1]).
itoa(0) -> "zero";
itoa(N) when is_float(N) -> no_float_support;
itoa(N) when N < 0 -> "negative " ++ itoa(abs(N));
itoa(N) when is_integer(N) -> itoa_render(N);
itoa(_) -> severe_error.
itoa_render(N) when N >= 1100, N < 10000, N rem 100 == 0, N rem 1000 /= 0 ->
itoa_render(N, ["", "hundred"], 100, []);
itoa_render(N) when N >= 1000 ->
itoa_render(N,["",
"thousand","million","billion","trillion","quadrillion","quintillion",
"sextillion","septillion","octillion","nontillion","dectillion"
],1000, []
);
itoa_render(N) when N >= 100, N rem 100 == 0 ->
itoa_render(N div 100) ++ " hundred";
itoa_render(N) when N >= 100 ->
Hun_diff = N rem 100,
itoa_render(N - Hun_diff) ++ [32 | itoa_render(Hun_diff)];
itoa_render(N) when N > 19, N rem 10 == 0 ->
lists:nth(N div 10 - 1, [
"twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"
]);
itoa_render(N) when N > 19 ->
Ten_diff = N rem 10,
itoa_render(N - Ten_diff) ++ "-" ++ itoa_render(Ten_diff);
itoa_render(N) when N > 0 ->
lists:nth(N, [
"one","two","three","four","five","six","seven","eight","nine",
"ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen",
"seventeen","eighteen","nineteen"
]);
itoa_render(_) -> []. % 0
itoa_render(0, _, _, After) -> After;
itoa_render(_, [], _, _) -> overflow;
itoa_render(N, [Magnitude | Remaining_Magnitudes], Factor, After) ->
This_OOM = itoa_render(N rem Factor),
This_Rep = if
This_OOM == [] -> [];
Magnitude == [] -> This_OOM;
true -> This_OOM ++ [32 | Magnitude] ++ if
After == [] -> [];
true -> [32]
end
end,
itoa_render(N div Factor, Remaining_Magnitudes, Factor, This_Rep ++ After).