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