Take a number and return English language representation 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)                    -&gt; "zero";
itoa(N) when is_float(N)   -&gt; no_float_support;
itoa(N) when N &lt; 0         -&gt; "negative " ++ itoa(abs(N));
itoa(N) when is_integer(N) -&gt; itoa_render(N);
itoa(_)                    -&gt; severe_error.

itoa_render(N) when N &gt;= 1100, N &lt; 10000, N rem 100 == 0, N rem 1000 /= 0 -&gt;
    itoa_render(N, ["", "hundred"], 100, []);
itoa_render(N) when N &gt;= 1000 -&gt;
    itoa_render(N,["",
        "thousand","million","billion","trillion","quadrillion","quintillion",
        "sextillion","septillion","octillion","nontillion","dectillion"
        ],1000, []
    );
itoa_render(N) when N &gt;= 100, N rem 100 == 0 -&gt;
    itoa_render(N div 100) ++ " hundred";
itoa_render(N) when N &gt;= 100 -&gt;
    Hun_diff = N rem 100,
    itoa_render(N - Hun_diff) ++ [32 | itoa_render(Hun_diff)];
itoa_render(N) when N &gt; 19, N rem 10 == 0 -&gt;
    lists:nth(N div 10 - 1, [
        "twenty","thirty","forty","fifty","sixty","seventy","eighty","ninety"
    ]);
itoa_render(N) when N &gt; 19 -&gt;
    Ten_diff = N rem 10,
    itoa_render(N - Ten_diff) ++ "-" ++ itoa_render(Ten_diff);
itoa_render(N) when N &gt; 0 -&gt;
    lists:nth(N, [
        "one","two","three","four","five","six","seven","eight","nine",
        "ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen",
        "seventeen","eighteen","nineteen"
    ]);
itoa_render(_) -&gt; []. % 0

itoa_render(0, _, _, After) -&gt; After;
itoa_render(_, [], _, _) -&gt; overflow;
itoa_render(N, [Magnitude | Remaining_Magnitudes], Factor, After) -&gt;
    This_OOM = itoa_render(N rem Factor),
    This_Rep = if
        This_OOM  == [] -&gt; [];
        Magnitude == [] -&gt; This_OOM;
        true            -&gt; This_OOM ++ [32 | Magnitude] ++ if
            After     == [] -&gt; [];
            true            -&gt; [32]
        end
    end,
    itoa_render(N div Factor, Remaining_Magnitudes, Factor, This_Rep ++ After).
At first glance, you're trying to be a bit cute here and it's making your code more complex than necessary.  For example, why not handle 11 and 12 as part of the teens and why not just type out the teen and decade names in full rather than having extra logic to append a not-quite common suffix ("teen" and "ty")?

For n &lt; 1000 you have the following rules (let &lt;n&gt; mean "n in words", % mean modulo, and // mean integer division):

if 100 &lt;= n then &lt;n // 100&gt; " hundred" ++ 
                 (if n % 100 == 0 then "" else " and " ++ &lt;n % 100&gt;)
if 20 &lt;= n then  {"", "twenty", ..., "ninety"}[n // 10] ++ 
                 (if n % 10 == 0 then "" else " " ++ &lt;n % 10&gt;)
otherwise        {"zero", "one", "two", ..., "ten", "eleven", ..., "nineteen"}[n]


Now you only need to deal with the orders of magnitude ("thousand", "million", etc.).