# [erlang-questions] lists:seq/[2,3] bug?

Richard A. O'Keefe <>
Mon Sep 22 02:36:51 CEST 2008

On 20 Sep 2008, at 3:30 am, Kostis Sagonas wrote:
> Despite all the shouting, I've yet to read a coherent argument why the
> case M = N - 1 is more special than e.g. the case M = N - 42.

That's not what I say; what I say is that it is *less* special.
The reason that M  = N - 1 is less special is ever so simple:
you can have a list with length 0, but you can't have a list
with length -41.  Surely this is obvious?

> [Please realize that similarly to "expect", the expression "makes
> sense"
> is also highly subjective.  I do not see why throwing an exception for
> M<N does not make sense.]

Because the empty list is a perfectly good list.
It should not be a special case.
Wouldn't you find it absurd if 0 div 10 raised an exception?
Zero is a sensible number.  [] is a sensible list.

>
> Haskell, where exceptions are problematic, at least is consistent in
> its
> behaviour.
Haskell has exceptions and uses them extensively.
For example, take n xs returns at most the first n elements
of the list xs; when n < 0 you get an exception.

> In Haskell the equivalent of lists:seq/2 defines a *total*
> function over the integers, not a function that returns [] in some
> special cases only. Disregarding for a moment that throwing exceptions
> in Erlang is OK, why would Erlang have a different behaviour ?

I want to remember length(lists:seq(A,Z)) = Z-A+1.
Nice, simple, exceptionless.
(As in, anything that would be an exception really is an
'exception'.)

I suspect that the Haskell designers didn't give a Contintental [%]
about exceptions.  They were after a simple specification too,
and theirs may have been something like
[a..z] is the set of all values x such that
a <= x <= z, listed in ascending order.
When z < a, there are no such values, so from that
specification you can deduce that the answer is [].
For some types, Haskell defines [a..z] to be (roughly)
takeWhile (<= z) [a..]
It would have been perfectly simple for the Haskell designers
to put
enumFromTo a z | a <= z = takeWhile (<= z) enumFrom a
enumFromTo a z = error "Prelude.enumFromTo: empty range"
in the standard prelude, had they wished to.  After all,
they did exactly that kind of thing for `take`.

I would actually be happy with something that matches Haskell
exactly here.  The important thing is to have a specification
that is simple, memorable, and precise.  Queer corner cases
(like arbitrarily excluding []) make a specification more
complex, harder to remember, and harder to use correctly.
>

> I repeat: If we were to change the behaviour of lists:seq/2 -- and so
> far I've not yet read something that convinced me we should -- how is
> the above different than e.g. lists:seq(8, 5) ?

I repeat, because 5-8+1 is -2, and you can't have a list of
length -2.  But you *can* have a list of length 0.

In the course of writing this message, I've asked in
When I get an answer, I'll pass it on.

[%] This is an Americanism, but my father used it, so it must be OK.
It refers to the "Continental currency" of the American Confederacy,
which became worthless when they lost the Civil War.