Steven Schveighoffer wrote:
When looking at ranges, it seems like a much better model for iteration than opApply. It seems like it could be a whole replacement for opApply. But when looking at the current usage of opApply, there are some holes.

foreach(i, x; range)
{
}

What exactly happens? Do you have to return a tuple from a range with head()?

One possibility I'd discussed with Walter is that for the usage above, the compiler asks for the .key property in addition to .head. If more keys are specified, .key1, .key2... are required. Probably an array would be a nicer solution.

Also, another thing that was nice about opApply, if you had multiple ways to iterate over an aggregate, you simply altered your arguments to foreach. How can this be implemented with ranges?

class Aggregate
{
   int opApply(int delegate(ref int idx, ref int value) dg) {...}
   int opApply(int delegate(ref int value) dg) {...}
}

Aggregate A = new Aggregate;
foreach(i, ref x; A) {...}
foreach(x; A) {...}

Keys will take care of that too. The "ref" thing will generate different code by taking the address of head (not sure if Walter implemented that).

Maybe ranges need some more functionality to do this. I can't see how to do it with Tuples, as you'd have to be able to overload head() based on return value. Or if a proposed opRange is supported from Aggregate (opRange is called if it exists, otherwise if the aggregate is a range use that, otherwise look for opApply), you'd have to overload the range type returned based on usage.

Yes, I'm afraid type deduction will be harmed with ranges.

The only thing I could think of is to change head and toe to take reference parameters instead of using the return value, although that's ugly. Maybe it could be supported in addition to returning a value?

[snip]

This is ugly, and requires some compiler magic, but do you see another way to do it? I didn't know if "ref ref" would work, so that's why I use pointers instead. Since ref is a storage class, I don't know if the compiler would overload anyways...

One simple solution to the overloading by return type would be to have head be a template. Then if you say:

foreach (int e; range) {}

the corresponding assignment for e will be:

int e = __r.head!(int)();

There are a few more wrinkles to fill with Botox though :o).


Andrei

Reply via email to