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

Reply via email to