MikeInnes / Lazy.jl

I was gonna maintain this package, but then I got high
Other
470 stars 54 forks source link

Regarding the returned type of `rest(::List)` and `drop(::List)` #41

Open boathit opened 8 years ago

boathit commented 8 years ago

In the current implementation the returned type of rest is LinkedList while drop returns LazyList,

> typeof(Lazy.rest(list(1,2,3)))
Lazy.LinkedList
> typeof(Lazy.drop(1, list(1,2,3)))
Lazy.LazyList

This not only seems inconsistent but also explains why the following code works unexpectedly,

> fibs = @lazy 0:1:(fibs + Lazy.rest(fibs));
> Lazy.take(5, fibs)
List:
  0
  1

If we convert the returned type of Lazy.rest to Lazy.LazyList it works correctly,

> fibs = @lazy 0:1:(fibs + @lazy Lazy.rest(fibs));
> Lazy.take(5, fibs)
List:
  0
  1
  1
  2
  3

Thus I suggest we change the returned type of rest(::List) to LazyList

MikeInnes commented 8 years ago

Actually rest can return either:

julia> Lazy.rest(constantly(1)) |> typeof
Lazy.LazyList

Both LinkedList and LazyList are part of the same data structure, the List, and should behave in exactly the same way – so there is a bug here, but that would be the wrong fix.

I'll take a look at this anyway.

MikeInnes commented 8 years ago

I think you're right that the issue here is that rest isn't lazily evaluated, although it doesn't always need to be lazy either. We can just overload it to be equivalent to drop when applied to a lazy list.

One could also argue that rest is defined as an eager version of drop and simply shouldn't be used here, but that's probably more confusing then helpful.