Can we get rid of opApply?

Jason House jason.james.house at gmail.com
Tue Jan 20 06:29:36 PST 2009


Andrei Alexandrescu Wrote:

> Steven Schveighoffer wrote:
> > "Andrei Alexandrescu" wrote
> >> 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.
> > 
> > I'd say labeling them "key" would be slightly biased.  The arguments to 
> > opApply might not always be considered a key.  I'd label them .head1, 
> > .head2, etc.
> 
> I agree.
> 
> > Also, how do you recreate this case:
> > 
> > struct S
> > {
> >    int opApply(int delegate(ref int idx, ref int v) dg) {...}
> >    int opApply(int delegate(ref string k, ref int v) dg) {...}
> >    int opApply(int delegate(ref int idx, ref string k, ref int v) dg) {...}
> > }
> > 
> > Think of S as a container that can look up values by index or by string 
> > (like a sorted dictionary).
> > 
> >> Probably an array would be a nicer solution.
> > 
> > I'm interested to hear what you mean by that.
> 
> Just that an array would be nicer than numbered properties.
> 
> >>> 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).
> > 
> > You mean taking the address of the return value from head?  Or using a 
> > delegate?  I'm not sure what you mean...  I'd be wary of performance if you 
> > mean take a delegate.
> 
> No delegate, just something like:
> 
> auto addr = &(__r.head);
> 
> then replace *addr throughout whenever the element is being used.
> 
> >>> 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.
> > 
> > BAD BAD BAD!  I love being able to do type deduction in foreach...  Not 
> > having that would be a real hard pill to swallow...
> 
> I hear ya. Please note that as far as this extension goes I'm just 
> making things up as I go while juggling one one-month-old kid on one 
> hand, two visiting parents on another hand, and one thesis on yet 
> another hand (paper accepted today... yay!).

Congratulations. I find that babies require at least 3 hands to preserve sanity.

 
> It would be great if you and/or others came with good proposals on how 
> to make ranges work well. For now, ranges only allow one iterated object 
> and one type, and I agree that that's a step backwards from opApply's 
> nice behavior. So far ref parameters and tuples have been mentioned. 
> Both have merit, and ref parameters have the additional advantage that 
> overloading and type deduction works with them.
> 
> 
> Andrei




More information about the Digitalmars-d mailing list