Sorry I haven't responded for so long... much going on in my world. On Mon, Jul 26, 2010 at 11:35 AM, Nicholas Clark <n...@ccl4.org> wrote:
> On Tue, Jul 20, 2010 at 07:31:14PM -0400, Aaron Sherman wrote: > > > 2) We deny that a range whose LHS is "larger" than its RHS makes sense, > but > > we also don't provide an easy way to construct such ranges lazily > otherwise. > > This would be annoying only, but then we have declared that ranges are > the > > right way to construct basic loops (e.g. for (1..1e10).reverse -> $i > {...} > > which is not lazy (blows up your machine) and feels awfully clunky next > to > > for 1e10..1 -> $i {...} which would not blow up your machine, or even > make > > it break a sweat, if it worked) > > There is no reason why for (1..1e10).reverse -> $i {...} should *not* be > lazy. > > As a special case, perhaps you can treat ranges as special and not as simple iterators. To be honest, I wasn't thinking about the possibility of such special cases, but about iterators in general. You can't generically reverse lazy constructs without running afoul of the halting problem, which I invite you to solve at your leisure ;-) For example, let's just tie it to integer factorization to make it really obvious: # Generator for ranges of sequential, composite integers sub composites(Int $start) { gather do { for $start .. * -> $i { last if isprime($i); take $i; } } } for composites(10116471302318).reverse -> $i { say $i } The first value should be 10116471302380, but computing that without iterating through the list from start to finish would require knowing that none of the integers between 10116471302318 and 10116471302380, inclusive, are prime. Of course, the same problem exists for any iterator where the end condition or steps can't be easily pre-computed, but this makes it more obvious than most. That means that Range.reverse has to do something special that iterators in general can't be relied on to do. Does that introduce problems? Not big ones. I can definitely see people who are used to "for ($a .. $b).reverse -> ..." getting confused when "for @blah.reverse -> ..." blows up their machine, but avoiding that confusion might not be practical. PS: On a really abstract note, requiring that ($a .. $b).reverse be lazy will put new constraints on the right hand side parameter. Previously, it didn't have to have a value of its own, it just had to be comparable to other values. for example: for $a .. $b -> $c { ... } In that, we don't include the RHS in the output range explicitly. Instead, we increment a $a (via .succ) until it's >= $b. If $a were 1 and $b were an object that "does Int" but just implements the comparison features, and has no fixed numeric value, then it should still work (e.g. it could be random). Now that's not possible because we need to use the RHS a the starting point when .reverse is invoked. I have no idea if that matters, but it's important to be aware of when and where we constrain the interface rather than discovering it later. -- Aaron Sherman Email or GTalk: a...@ajs.com http://www.ajs.com/~ajs