A possible solution for the opIndexXxxAssign morass

Lars T. Kyllingstad public at kyllingen.NOSPAMnet
Wed Oct 14 02:12:46 PDT 2009


Don wrote:
> Lars T. Kyllingstad wrote:
>> Don wrote:
>>> Andrei Alexandrescu wrote:
>>>> Right now we're in trouble with operators: opIndex and opIndexAssign 
>>>> don't seem to be up to snuff because they don't catch operations like
>>>>
>>>> a[b] += c;
>>>>
>>>> with reasonable expressiveness and efficiency.
>>>>
>>>> Last night this idea occurred to me: we could simply use overloading 
>>>> with the existing operator names. Consider:
>>>>
>>>> a += b
>>>>
>>>> gets rewritten as
>>>>
>>>> a.opAddAssign(b)
>>>>
>>>> Then how about this - rewrite this:
>>>>
>>>> a[b] += c
>>>>
>>>> as
>>>>
>>>> a.opAddAssign(b, c);
>>>>
>>>> There's no chance of ambiguity because the parameter counts are 
>>>> different. Moreover, this scales to multiple indexes:
>>>>
>>>> a[b1, b2, ..., bn] = c
>>>>
>>>> gets rewritten as
>>>>
>>>> a.opAddAssign(b1, b2, ..., bn, c)
>>>>
>>>> What do you think? I may be missing some important cases or threats.
>>>>
>>>>
>>>> Andrei
>>>
>>> Well timed. I just wrote this operator overloading proposal, part 1.
>>> http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP7
>>> I concentrated on getting the use cases established.
>>>
>>> The indexing thing was something I didn't have a solution for.
>>>
>>> BTW we need to deal with slices as well as indexes. I think the way 
>>> to do this is to make a slice into a type of index.
>>
>>
>> I like the idea of enforcing relationships between operators. In fact, 
>> I think we can take it even further, and require that operator 
>> overloading in general *must* follow mathematical rules, and anything 
>> else leads to undefined behaviour. For example, if n is an integer, a 
>> and b are scalars, and x and y are general types, the compiler should 
>> be free to rewrite
>>
>>          n*x  <-->  x + x + ... + x    <-->  2*x + 2*x + ...
>>         x^^n  <-->  x * x * ... * x    <-->  x^^2 * x^^2 * ...
>>    x/a + y/b  <-->  (b*x + a*y)/(a*b)
>>
>> and so on, based on what it finds to be the most efficient operations. 
> 
> Unfortunately, the last one doesn't work for reals. a*b could overflow 
> or underflow.
> x/ real.max + y / real.max   is exactly 2.0 if x and y are both real.max
> But
> (real.max * x + real.max *y)/(real.max * real.max) is infinity/infinity 
> = NaN.

Good point. I am thinking like a mathematician, not a programmer. :)


> The others don't always work in general, either. I'm worried about 
> decimal floats. Say n==10, then it's an exact operation; but addition 
> isn't exact. It always works for n==2, since there's at most one 
> roundoff in both cases.

But the case x*2 --> x+x would also likely be the most common in terms 
of optimisation, right?


> But I do feel that with floating-point, we've lost so many identities, 
> that we must preserve every one which we have left.
> 
>> (Note how I snuck my favourite suggestion for an exponentiation 
>> operator in there. I *really* want that.)
> 
> I want it too. Heck, I might even make a patch for it <g>.

If you do, make sure to announce it loudly and clearly on the NG. Don't 
want to miss it. ;)

-Lars



More information about the Digitalmars-d mailing list