[erlang-questions] How can I make a list of this

Richard A. O'Keefe ok@REDACTED
Thu Aug 20 08:51:07 CEST 2015


On 20/08/2015, at 6:17 pm, Roelof Wobben <r.wobben@REDACTED> wrote:
> The other part is that I "just" started with Erlang so the language is unfamiliir in terms of
> which part casn help me solve the problem. Is it a LC  or a map or just pattern matching.

Anything that can be done with a list comprehension can be done
without it.

TL;DR	Master these four list processing functions:
	lists:map(Transformer, Elements)
	lists:filter(Tester, Elements)
	lists:foldl(Updater, Initial, Elements)
	lists:append(List_Of_Lists)


Let's generalise the current example a bit.
We want to compute

   [f(X,Y) || X <- g(U), Y <- h(X)]

We can do it by writing our own recursive functions.

answer(U) ->
    lists:reverse(outer(g(U), [])).

outer([], L) ->
    L;
outer([X|Xs], L) ->
    outer(Xs, inner(h(X), U, L)).

inner([], _, L) ->
    L;
inner([Y|Ys], X, L) ->
    inner(Ys, X, [f(X,Y)|L]).

This builds the answer up from left to right
using an accumulator, but that produces the
wrong order, so we fix it up with reverse.

To adapt this to a particular problem, plug in
appropriate expressions in place of g(U), h(X),
and f(X,Y).  If you're going to sort the answer
anyway, there's no point in reversing first.

Let's put this another way.
List comprehensions are pleasantly brief and
clear, but they do not add to the power of the
language.  SML manages fine without them.
Any list comprehension can be written using
some combination of

    lists:map(F, Xs)
	-- [F(X) || X <- Xs]
    lists:filter(P, Xs)
	-- [X || X <- Xs, P(X)]
    lists:append(Xss)
	-- [X || Xs <- Xss, X <- Xs].

You should make sure that you understand these
three functions thoroughly.  A fourth function,

    lists:foldl(F, A, Xs)

is also important to understand.

In the case of

    [f(X,Y) || X <- g(U), Y <- h(X)]

we have to

    (1) traverse g(U), for which map seems appropriate
    (2) traverse h(X), for which map seems appropriate
    (3) but that yields a list of lists, so we need append

    lists:append(lists:map(
        fun (X) -> lists:map(
            fun (Y) ->  f(X, Y) end, h(X))
        end, g(U)))

List comprehensions add no computational power to
map/2, filter/2, and append/1.  The difference is
brevity and clarity, that's all.

A beginner had better keep the bodies of 'fun's simple.
Simpler than this.  So maybe

    Outer = fun (X) ->
        Inner = fun (Y) -> f(X, Y) end,
        lists:map(Inner, X)
    end,
    lists:append(lists:map(Outer, g(U))).








More information about the erlang-questions mailing list