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

Richard A. O'Keefe <>
Fri Sep 19 04:30:33 CEST 2008


On 18 Sep 2008, at 10:21 pm, Zvi wrote:
> 1. if you already dealing with it, can you also extend it to floats  
> too?
> I.e. if step is float, then the resulting list must be floats too.

Let me explain why this was an issue for me.
I sometimes do things in Haskell and sometimes in Erlang.
[3..2] is an empty list in Haskell.
It makes life just that little bit harder if I can't do that in Erlang.

Haskell does support [a..z] and [a,b..z] for floating point numbers.

Since (a) floating-point loops are a little bit tricky
(taking X[i+1] = X[i]+delta and
  taking X[i] = X[0]+i*delta
  give *different* answers, with the latter being slightly more  
accurate,
  and IEEE hasn't fixed all portability issues
) and (b) in current Erlang, lists:seq/2 and lists:seq/3 provide type
information for the Dialyzer, which I for one would be very reluctant
to break,

I suggest that the way to handle floating point ranges would be to
add two new functions:
   lists:float_seq(First, Last)
   lists:float_seq(First, Last, Inc)


> 2. I'm all about common sense, and behaviour we expect must be  
> consistent
> with similar constructs in other languages from Basic to Matlab.
> Python's   "range([start,] stop [,step]) -> list of integers"   
> construct  is
> not a good example, b/c "stop" isn't included (which is counter- 
> intuitive)
> and it's also defined only on integers. See example at the end of the
> message.

To every example there is an equal and opposite example.
In R, if x <= y, then x:y is x,x+1,...,y
   but if x < y,  then x:y is y,y-1,...,x
so that 1:3 is 1 2 3, 1:2 is 1 2, 1:1 is 1, but 1:0 is 1 0.
(This may be the most hated thing about R, that 1:n does not work
when n might be 0, so you have to say seq(from = 1, length = 0).)

Haskell provided the motivation, but the reason I how to persuade
Erlangers to make lists:seq(X, X-1) return [] is to make Erlang
more consistent with ITSELF.
>

> 3. Step = 0
> Also Erlang handles well case when Step=0, while both Matlab and  
> Python not:

Oddly enough, [1..1] => [1] in Haskell,
but [1,1..1] => [1,1,1,1,1,1,1,1.......

I see Step = 0 as very much a special case; it doesn't really fit well
with the rest of the specification.  However, I certainly don't want
to break any code that might rely on it.

> 3. Syntax.
> Also will be good to have operator or parse-transform, which  
> converting
> something like "[N..M]"  to "lists:seq(N,M)" or "[N1,N2..M]" to
> "lists:seq(N1,M,N2-N1)"

It's pretty, certainly.  I think we can do without it, though.

> 4 Is this possible to have iterator or lazy evaluated sequence in  
> Erlang?
> I.e. in code like this:
>
> Sum = lists:sum( [X*X || X<-lists:seq(1,1000000)] ).
>
> Do I really need to allocate list of 1000000 elements, just to be  
> able to
> use List Comprehension construct?

We don't need special purpose evaluation strategies for this,
just for the compiler to recognise X <- lists:seq(A, Z[, D]) and
do something special with it.  In this case, you have *two* lists
that you don't need, and

     sum(First, Last, F) ->
	sum_loop(First, Last, F, 0).

     sum_loop(First, Last, F, S) when First =< Last ->
	sum_loop(First+1, Last, F, S + F(First));
     sum_loop(First, Last, _, S) when First > Last ->
	S.
...
     Sum = sum(1, 1000*1000, fun (X) -> X*X end)

isn't _that_ hard to come up with.  It would be nice to have an Erlang
compiler that did cross-module inlining and deforestation.  It's not
going to happen soon.

> 5 Last thing, I think that function like this must be implemented in  
> native
> code in the VM itself, like lists:reverse.

My concern here is whether the function(s) should have a value or not
in certain cases.  However, it's always a good idea to try things.

Imagine my surprise, on a Mac (and therefore without HiPE), to find
that reverse/1 coded in Erlang was only 3 times slower than the
built-in one.  On a SPARC, loaded with c(...,[native]), the result
was 2 times slower than the built-in one, but I had to use
ridiculously long lists to measure it.  (And there's even one test
result, with length 100*1000, where the Erlang code was faster...)

List reversal turns up a lot more than sequence generation, so it
makes sense to speed that up, even if it is just by a factor of 2.




More information about the erlang-questions mailing list