Dave Whipp wrote:
Okay, thinking a bit about this, I agree that there are times when you want multiple lazy lists going on at the same time. But, frankly if the lists are lazy, why shouldn't the programmer be lazy as well?gather @bin1, @bin2 -> $bin1, $bin2{
for @words {
$bin1.take if /^^a/;
$bin2.take if /e$$/;
}
}
Juerd point out (private email) that my example doesn't really make any sense in that it doesn't do anything over and above s/take/push.
However, I think the concept of multiple bins could still be useful. My understand of gather/take is that the function that does the "gather" is coroutined (if that's a verb) against the block that does the gathering. So to be able to usefully use multiple streams, the "gather" would need to fork into multiple threads that are then interleaved with the "gather" block. Calling a function in junctive context does the forking bit, so a gather that gathered in a junctive context might make sense as a serialization mechanism. I can't quite work out what the syntax would be for that though.
@bin1 = gather { for @words { take if /^^a/; } }
@bin2 = gather { for @words { take if /e$$/; } }
Two lazy lists? Two gathers! Since they are lazy, you can eval them in order you please.
I see a problem with attempting to put the two into one statement. In your example above, if you wanted something from @bin2, you could have to process a whole lot of things into @bin1, just to get the next element out of @bin2. In fact, you could easily end up processing all of @words, and filling @bin1, only to discover that @bin2 is empty. To me this kind of forced-fill of @bin1 is a complete defeat of the entire concept of _lazy_ lists.
There's also the issue of from what I understood of gather/take before (still awaiting a proper definition), gather returns a lazy list. So it's not C<gather @bin1 { ... }>, it's C<@bin1 = gather {...}>. What would your C<gather> return? A list of lazy lists? How do you easily tell the difference between a list of lazy lists and a lazy list? I think it's better to leave a 1::1 gather::list ratio, as that will cover some {insert randomly high %age} of all cases. For the other cases, you're likely better off building a class with two emitter methods, and possibly even use C<tie> to make it look like two lazy lists.
-- Rod Adams
The thing about lists is that they are linear. They are, by definition, a sequence of single items. Now, that 'single item' may very well be a reference to something non-trivial, but to the list it's a single value.