So, to clarify, Iterators aren't a thing in themselves. Iteration is an 
interface, and to call something an iterator just means that you can put it 
in a for loop. Tasks and Lazy Lists are both iterators; so are arrays, 
sets, dictionaries, and a whole bunch of other things. But although you can 
use them in a similar way if you want to, they are all designed to solve 
very different problems.

Now, Tasks and Lazy Lists do look similar in that you can produce and 
consume a stream of values with both, but conceptually they are quite 
different - Tasks are a mechanism for control flow, whereas Lazy Lists are 
a data structure. Perhaps you could call them the procedural and functional 
analogies of each other. I can't tell you what's best for you, but if 
you're thinking of Tasks as representing a sequence of data, then there's a 
good chance you'll find Lazy Lists easier to reason about.

For example, consider the partition() function. In Lazy.jl terms this 
splits a single list into a list of lists - it's fairly easy to visualise 
this:

> partition(3, seq(1:9))
List:
  (1 2 3)
  (4 5 6)
  (7 8 9)

If you wanted to write partition() for Tasks, you'd end up with tasks that 
produce tasks. I don't know about you, but that gives me a headache.

You'll also notice that working with general iterators takes a lot of work; 
consider the Iterators.jl version of take(), which takes about twenty 
lines, versus the two-liner in Lazy.jl. Some things are simply impossible 
to do generically, like flatten().

That's not to say that Tasks aren't useful - they're better if you want to 
do more things in terms of control flow and less in terms of manipulating 
the data itself, for example. Both Tasks and Lazy Lists are extremely 
powerful, but each within their own scope - hence it's useful to have both.

Is this roughly what you were looking for? Let me know if I've missed 
anything.

Reply via email to