newbie question: flat_length example

Richard A. O'Keefe <>
Mon Jun 12 03:23:16 CEST 2006


"Quan Ta" <> wrote:
	-module(list2).
	-export([flat_length/1]).
	
	%% flat_length(List)
	%%  Calculate the length of a list of lists.
	
Why are you writing a function that is already there
(lists:flatlength/1)?

	flat_length([H,T], N) when list(H) ->
----------------------^

The error is almost certainly there; a comma where there
should be a vertical bar.

	    flat_length(T, flat_length(H, N));

Erlang's lists:flatten/1 is rather odd.
The traditional specification of flatten in Lisp goes something like this:

    (define (flatten L)
        (if (pair? L)
            (append (flatten (car L)) (flatten (cdr L)))
            (if (null? L)
                '()
                (list L))))

from which we conclude that (flatten 27) ==> (27).
The Erlang version,

    flatten(List) when list(List) ->
        do_flatten(List, []).

    do_flatten([H|T], Tail) when list(H) ->
        do_flatten(H, do_flatten(T, Tail));
    do_flatten([H|T], Tail) ->
        [H|do_flatten(T, Tail)];
    do_flatten([], Tail) ->
        Tail.

makes the top level quite inconsistent with lower levels.  Why?
Why should lists:flatten($x) crash instead of answering "x"?

The definition of lists:flatlength/1 (andwhyisthenameruntogetherlikethat?)
is this:

flatlength(List) ->
    flatlength(List, 0).

flatlength([H|T], L) when list(H) ->
    flatlength(H, flatlength(T, L));
flatlength([_|T], L) ->
    flatlength(T, L + 1);
flatlength([], L) -> L.

This structure is similar (but not identical) to the structure of
flatten/1.  For the sake of efficiency, it shouldn't be.  The first
clause of flatlength/2 should be

    flatlength([H|T], L) when list(H) ->
	flatlength(T, flatlength(H, L));




More information about the erlang-questions mailing list