Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

the seq function doesn't produce a lazy list in many use cases: #95

Open
GordonBGood opened this issue Sep 8, 2018 · 3 comments
Open

Comments

@GordonBGood
Copy link

GordonBGood commented Sep 8, 2018

The seq methods in "liblazy.jl" don't produce a LinkedList with the tail a succession of LazyList's for many use cases as seems to be the obvious intention. One method includes the comment: # there should maybe be a @lazy here, but tests pass, but the reason the tests pass is that they never actually check that a true nested LazyList is created at the tail. The problem is that not enough attention is paid to the definition of Type's, which is a common problem in users of dynamically typed languages.

For the method following:

seq(xs::List) = xs

just passes the argument if it is a the abstract List type, but the abstract List type includes the LinkedList type which will get passed unaltered. This can be fixed by defining this first method as follows:

seq(xs::LazyList) = xs

which passes a LazyList unaltered but all other forms of List get handled by other methods, such as the one for iterations in the case of LinkedList; this leaves the type EmptyList not handled, for which I actually disagree with the definition anyway, but for now can be handled by the following:

seq(xs::EmptyList) = xs)

The methods for Tuple and Array are terribly inefficient in allocating new Array's just dropping the first element for each iteration (partially fixed by using @view, but completely unnecessary as both are iterable, presumably efficiently, and aren't needed at all as the general case for iterables will handle them.

The default general method(s) for iterables have the major problem that they return the results of the prepend function which returns a tail of a LinkList and not a LazyList. This can be fixed for both by forcing the tail to be a LazyList as follows:

function seq(itr, state = itr)
  xs = iterate(itr, state)
  xs == nothing && return EmptyList()
  x, state = xs
  prepend(x, LazyList(() -> seq(itr, state)))
end

Finally, let's turn to testing to see why this wasn't caught, lets improve the tests to see if we are generating real LazyList's - no type checking was done whatsoever::

isa(typeof(seq([1,2,3])), Lazy.LazyList) == true # reports false when it should be true
isa(typeof(seq(1:3)), Lazy.LazyList) == true # reports false when it should be true

Consideration of type and type stability is seriously flawed in this library.

@pfitzseb
Copy link
Collaborator

pfitzseb commented Sep 8, 2018

Thanks for the very detailed analysis. Would you consider opening a pull request which implements the improvements and tests you outlined?

@GordonBGood
Copy link
Author

GordonBGood commented Sep 8, 2018

I have the time and would be happy to issue a PR, but the problem with this library goes further than this single issue. I am currently preparing another issue, which once submitted will be the cause of (much) further discussion. Let's communicate once that is posted.

@GordonBGood
Copy link
Author

I have the time and would be happy to issue a PR, but the problem with this library goes further than this single issue. I as currently preparing another issue, which once submitted will be the cause of (much) further discussion. Let's communicate once that is posted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants