Can we get rid of opApply?

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Mon Jan 19 13:00:16 PST 2009


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



More information about the Digitalmars-d mailing list