I happend to read a new (to me) blog, Thoughts on life, computers, and eternal happiness. The lead post featured some Erlang code, presented with very nice syntax coloring. I asked the author how he managed that.

Emacs. Of course. He had used a package called htmlize.el. Emacs never ceases to surprise me with new functionality.

Here is the binary search code from my previous post, this time in color. It looks much better, and is easier to read. Thanks, Jonathan, and much thanks to the author of htmlize.el, Hrvoje Niksic.

The downside is that while the version rendered on the glass looks great, the htmlized source is pretty much useless as erlang code, because it is totally encrusted with html markup. I’ll make a point of supplying the corresponding plain erlang code in any cases where I display htmlized code.

-module(binsearch).
-export([search/2, test/1]).
%------------------------------------------------------------------------------
%% Return a random integer in 2 .. 5, or return 0
%% In particular, do not return 1; used for generating test cases
%------------------------------------------------------------------------------
rint() ->
    rint(5).

rint(Limit) ->
    Chance = random:uniform(Limit),
    if
        Chance == Limit -> 0;
        true -> 1 + random:uniform(Limit)
    end.

%------------------------------------------------------------------------------
%% Return a length N list of integers in non-decreasing order
%% 1: repeated elements can occur,
%% 2: distinct consecutive elements must differ by at least 2
%% rint and rlist were designed to force these properties, useful in tests
%------------------------------------------------------------------------------
rlist(N) ->
    rlist(N, []).

rlist(0, Result)->
    lists:reverse(Result);

rlist(N, []) ->  %% might as well include some negs
    rlist(N-1, [-100]);

rlist(N, [H|T]) ->
    rlist(N-1, [H+rint(),H |T]). %%non-decreasing by construction

%% avoid magic constant
failure() -> -1.

%% take care of trivial 0 element case in binary searh
search(_, []) -> failure();

%% List is a list of integers
%% K is an integer; return index of K in List, or failure()
search(K, List)->
    search(K, List, 1, length(List) ).

%% Lo and Hi inclusively bound the portion
%% of List to be searched for K
search(K, List, Lo, Hi) ->
    if
        Hi < Lo -> failure();
        true ->
            Probe = (Lo + Hi) div 2,
            Elt = lists:nth(Probe, List),
            if
                K < Elt ->
                    search(K,List,Lo,Probe-1);
                K > Elt ->
                    search(K,List,Probe+1,Hi);
                true  ->   %% when K == elt
                    Probe
            end
    end.

testcase(N) ->
    List = rlist(N),
    Value = lists:nth(random:uniform(N), List),

    %% we know Value is in List
    Value = lists:nth(search(Value, List), List),

    %% we know some other values not in the list
    Failed = failure(),
    Failed = search(Value+1, List),
    Failed = search(Value-1, List),
    Failed = search(lists:nth(N,List)+1, List),
    Failed = search(lists:nth(1,List)-1, List),

    %% return 1 if the searches do not cause an exception
    1.

test(NumCases) ->
    test(NumCases, 0).
test(0, NumCorrect) ->
    NumCorrect;
test(M, NumCorrect) ->
    test(M-1, NumCorrect + testcase(random:uniform(100))).