[erlang-questions] create list quesion

Richard A. O'Keefe ok@REDACTED
Fri Jan 30 06:00:07 CET 2015


On 28/01/2015, at 3:15 am, Roelof Wobben <r.wobben@REDACTED> wrote:
> I try now to solve a challenge where I must make a list  from a range,
> 
> So for example if I do create(2) the outcome have to be [ 1, 2]

create(N) -> lists:seq(1, N).

> So i can do
> 
> create(0) ->
>  print array

Eh?  What has *[x]CREATING a [y]LIST* got to do with
*[x’]PRINTING an [y’]ARRAY*?

> but as far as I know the list is then not in the scope so I cannot use it when I do

What list?  Which scope?
> 
> create(2) ->
>  add the 2 to the array.

What array?  You said list!
> 
> How do I take care that the list is in the scope and still using only create(number)
> 
> Can anyone give me a tip about it ?

Let me demonstrate the thinking process.

-- A number range 1 to n
-- * is a special case of a number range l to u with l = 1 and u = n.

-- WHY?  We are going to need some sort of induction.
-- Maybe it will be easy to drive the upper bound down,
-- maybe it will be easier to drive the lower bound up,
-- but we can't do that to a bound that is a constant.
-- Generalising from 1..N to L..U will give us a CHOICE about
-- which bound to do the induction on.


-- A number range l to u
-- * begins with l and continues with (l+1) to n if l <= u;
-- * is empty if l > u.

-- WHY?  We can think about the INPUT to a function, but we can
-- also think about the OUTPUT of a function.  If the output is
-- a list, it could be empty.  When is it empty?  It could be
-- non-empty.  In that case, what are the head and tail?  Where
-- do they come from?

range1(N) -> range(1, N).

range(L, U) when L =< U -> [L | range(L+1, U)];
range(L, U) when L >  U -> [].

Now this uses body recursion, so we might twist it a bit to get tail
recursion.

-- A number range l to u
-- * is a special case of a number range l to u prepended to a list
--   r where r = [].

-- A number range l to u prepended to a list r
-- * is a number range l to (u-1) prepended to (u:r)
--   when l <= u;
-- * is r when l > u.

So

range(L, U) -> range(L, U, []).

range(L, U, R) when L =< U -> range(L, U-1, [U|R]);
range(L, U, R) when L > U  -> R.

You will notice that the first version of range/2 drives the lower
bound UP while the second version drives the upper bound DOWN.
Generalising from range1 did pay off.

You will also notice that the magic numbers 0 and 2 did not appear
anywhere, and that the thought process does not mention "scope" at
all.


In the questions you've been asking so far, you are still dealing
with the "functional programming" aspects of Erlang, where it
strongly resembles many other languages in the kind of thinking
required to deal with immutable structured data.

You will find you need to change mental gears at least twice more:
(1) penetrating to the heart of Erlang, namely concurrency.
Erlang concurrency has been imitated by some other languages.
(2) Getting to grips with the muscle of Erlang, the OTP libraries
and the ways of structuring complete systems.  This is where
Erlang gets to be quite different from other languages.






More information about the erlang-questions mailing list