Can we get rid of opApply?

Steven Schveighoffer schveiguy at yahoo.com
Tue Jan 20 07:05:07 PST 2009


"Andrei Alexandrescu" wrote
> Steven Schveighoffer wrote:

>> "Andrei Alexandrescu" wrote
>>> 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.

Ah, ok.  I still would be concerned with cases where you had more than one 
key and wanted a subset.  I suppose a different struct per key combination 
would be a solution, but it would be nice if the types played into it 
somehow.

>
>>>> 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.

OK, that is what I was thinking, sounds good.

>>>> 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!).

No worries.  My first just turned 8 months today :)  So I hear ya too. 
Congrats!

> 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.

However, the disdavantage to ref parameters is that you cannot have a ref 
ref parameter (i.e. one where you set a ref local inside the head method). 
A double pointer is all I could come up with.

My preference is for ref parameters since that is the most straightforward 
solution, and requires less code duplication, but there would have to be 
some help from the compiler.  We probably don't want to use double-pointer 
args as that would be illegal in SafeD, perhaps we need a new type 
constructor that is like ref?  Or maybe a library solution could give us a 
double-ref, as long as the compiler optimized out the wrapper.

-Steve 





More information about the Digitalmars-d mailing list