[erlang-questions] lists:seq/[2,3] bug?
Richard A. O'Keefe
<>
Thu Sep 18 09:27:57 CEST 2008
On 18 Sep 2008, at 7:05 pm, Nicolas Charpentier wrote:
> Richard A. O'Keefe wrote:
> > On my Mac I have Erlang R12B-3.
> > erl -version says
> > Erlang (SMP,ASYNC_THREADS) (BEAM) emulator version 5.6.3
> >
> > lists:seq(1, N) gives me the expected N-element list for
> > integers N >= 1. I expect, indeed, I would require, that
> > lists:seq(1, 0) should give me the empty list. Instead,
> >
>
> Hi,
>
> According to the documentation, the meaning of the first argument is
> the first value and the second one is the *final* value of the
> sequence not the length of the sequence.
Nobody, least of all me, ever said, thought, or for one instant
imagined that the last argument was supposed to be the length of the
sequence.
Perhaps the fact of my example starting at 1 confused you.
What I supposed about the length is no more than what is true:
L = lists:seq(Min, Max)
implies
length(L) == Max - Min + 1.
What I want is for this to hold in ALL cases where it COULD hold,
including the empty list case length(L) == 0, when Max = Min - 1.
Here's another example:
lists:seq(5, 7) => [5,6,7]
lists:seq(5, 6) => [5,6]
lists:seq(5, 5) => [5]
lists:seq(5, 4) *SHOULD* => [] but actually blows up.
>
> I think that your proposition will break a lot of code.
Why do you think that? The correction I want ONLY affects
cases where the current version blows up; whenever the
current version returns any answer at all, mine returns the
same one.
>
> Some example of lists:seq usage.
>
> Erlang (BEAM) emulator version 5.6.3 [source] [smp:2] [async-threads:
> 0] [hipe] [kernel-poll:false]
>
> Eshell V5.6.3 (abort with ^G)
> 1> lists:seq(2,3).
> [2,3]
Works with my code.
>
> 2> lists:seq(2,0,-1).
> [2,1,0]
I only provided model code for seq/2, but yes,
with my code this also works identically.
The only difference is that with my code
seq(-1, 0, -1) => [] instead of wrongly blowing up.
Here's the code with 'typer' specs.
-spec(seq/2 ::
(integer(),integer()) -> [integer()]).
seq(Min, Max) when is_integer(Min), is_integer(Max), Min-1 =< Max ->
seq_loop(Max-Min+1, Max, []).
-spec(seq_loop/3 ::
(non_neg_integer(),integer(),[integer()]) -> [integer()]).
seq_loop(N, X, L) when N >= 4 ->
seq_loop(N-4, X-4, [X-3,X-2,X-1,X|L]);
seq_loop(N, X, L) when N >= 2 ->
seq_loop(N-2, X-2, [X-1,X|L]);
seq_loop(1, X, L) ->
[X|L];
seq_loop(0, _, L) ->
L.
-spec(seq/3 ::
(integer(),integer(),integer()) -> [integer()]).
seq(Min, Max, Inc) when is_integer(Min), is_integer(Max),
is_integer(Inc) ->
if Inc > 0, Min - Inc =< Max ->
N = (Max - Min + Inc) div Inc,
seq_loop(N, Inc*(N-1)+Min, Inc, [])
; Inc < 0, Min - Inc >= Max ->
N = (Min - Max - Inc) div (-Inc),
seq_loop(N, Inc*(N-1)+Min, Inc, [])
; Inc == 0, Min == Max ->
[Min]
end.
-spec(seq_loop/4 ::
(non_neg_integer(),integer(),integer(),[integer()]) ->
[integer()]).
seq_loop(N, X, D, L) when N >= 4 ->
Y = X-D, Z = Y-D, W = Z-D,
seq_loop(N-4, W-D, D, [W,Z,Y,X|L]);
seq_loop(N, X, D, L) when N >= 2 ->
Y = X-D,
seq_loop(N-2, Y-D, D, [Y,X|L]);
seq_loop(1, X, _, L) ->
[X|L];
seq_loop(0, _, _, L) ->
L.
More information about the erlang-questions
mailing list