October 13, 2009
On Tue, 13 Oct 2009 12:44:21 -0400, Denis Koroskin <2korden@gmail.com> wrote:

> Another thing I dislike about this proposal is that "a[b] += c;" translates into "opAddAssign" and doesn't mention "index" while "a[b] = c;" does ("opIndexAssign").

I think the optimization translates to opAssign as well:

a[b] = c; => a.opAssign(b, c);

On Tue, 13 Oct 2009 12:37:50 -0400, Bill Baxter <wbaxter@gmail.com> wrote:

> Huh? It didn't sound to me like it would get rid of anything, except
> for the use of the word "index" in many methods that have to do with
> index operations.  That just seems confusing to me.   I think the
> opIndexXxxAssign functions may need to be added, but adding them by
> overloading existing names doesn't seem a win to me.

The point is to avoid having operator function names multiply out of control.  Re-examining it, I agree with you -- It makes little sense to have an operator that involves an indexing lack the term Index.

If only there was a way to make the indexing orthogonal to the other operation.  For example something like:

struct X
{
   private int[] arr;
   opIndex(int idx) // declares a new "namespace" where idx is an implicitly passed argument
   {
      int opAssign(int x)
      {
         arr[idx] = x;
         return x;
      }
   }
}

I know this probably doesn't parse well, should opIndex be a keyword? or an attribute?

-Steve
October 13, 2009
Bill Baxter wrote:
> Huh? It didn't sound to me like it would get rid of anything, except
> for the use of the word "index" in many methods that have to do with
> index operations.  That just seems confusing to me.   I think the
> opIndexXxxAssign functions may need to be added, but adding them by
> overloading existing names doesn't seem a win to me.
> 
> --bb

That's a good point. But something is inherently problematic about name explosion (In the proposed solution there is still an explosion in the count of functions that need to be written.)

Now I realize there's also a need for opSliceXxxAssign, bleh. Unless we ascribe a distinct type to a .. b.


Andrei
October 13, 2009
On Tue, Oct 13, 2009 at 10:00 AM, Steven Schveighoffer <schveiguy@yahoo.com> wrote:
> On Tue, 13 Oct 2009 12:44:21 -0400, Denis Koroskin <2korden@gmail.com> wrote:
>
>> Another thing I dislike about this proposal is that "a[b] += c;" translates into "opAddAssign" and doesn't mention "index" while "a[b] = c;" does ("opIndexAssign").
>
> I think the optimization translates to opAssign as well:
>
> a[b] = c; => a.opAssign(b, c);
>
> On Tue, 13 Oct 2009 12:37:50 -0400, Bill Baxter <wbaxter@gmail.com> wrote:
>
>> Huh? It didn't sound to me like it would get rid of anything, except for the use of the word "index" in many methods that have to do with index operations.  That just seems confusing to me.   I think the opIndexXxxAssign functions may need to be added, but adding them by overloading existing names doesn't seem a win to me.
>
> The point is to avoid having operator function names multiply out of control.  Re-examining it, I agree with you -- It makes little sense to have an operator that involves an indexing lack the term Index.
>
> If only there was a way to make the indexing orthogonal to the other operation.  For example something like:
>
> struct X
> {
>   private int[] arr;
>   opIndex(int idx) // declares a new "namespace" where idx is an implicitly
> passed argument
>   {
>      int opAssign(int x)
>      {
>         arr[idx] = x;
>         return x;
>      }
>   }
> }
>
> I know this probably doesn't parse well, should opIndex be a keyword? or an attribute?

I don't think the number of /names/ required is the problem.  It's just the sheer number of functions themselves that's the issue.  I think a lot of that could mostly be fixed by some smart macros.   And until they exist, mixins can help.

struct Vec
{
    float x,y,z;
mixin(implementOperators("+ - / * += -= /= *=",
     q{
           a.x op= b.x;
           a.y op= b.y;
           a.z op= b.z;
     });
}

The code gives a list of operators to implement and one prototypical op= body.  With a smart enough CTFE string function that's all you need to generate all the listed operators.  Not sure how to work index operators into that.

--bb
October 13, 2009
This idea along with a slice overload would save me a lot of pain and performance while working with matrices in my production code. Any ideas when this could be implemented in D1?
Jonathan

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
October 13, 2009
On Tue, Oct 13, 2009 at 10:08 AM, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> Bill Baxter wrote:
>>
>> Huh? It didn't sound to me like it would get rid of anything, except for the use of the word "index" in many methods that have to do with index operations.  That just seems confusing to me.   I think the opIndexXxxAssign functions may need to be added, but adding them by overloading existing names doesn't seem a win to me.
>>
>> --bb
>
> That's a good point. But something is inherently problematic about name explosion (In the proposed solution there is still an explosion in the count of functions that need to be written.)
>
> Now I realize there's also a need for opSliceXxxAssign, bleh. Unless we ascribe a distinct type to a .. b.

Yeh, the name explosion is just a symptom of the real problem, which is function count explosion.  That's what needs fixing, if anything. But I don't really think having a lot of functions is the issue, it's implementers having to *write* a lot of boring repetitive functions that is the problem.  So if the drudgery can be automated somehow (in the cases where the pattern is regular), then that would solve the problem in my mind.  Even if it was still a function explosion under the hood.

--bb
October 13, 2009
On Tue, 13 Oct 2009 11:56:36 -0400, Don <nospam@nospam.com> 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've mentioned this problem before, in relation to multi-dimensional arrays:

// Slice a row out of an Matrix
row0 = myMatrix[0,0..$];

So basically, opIndex and opSlice need to merge to support this use case. I've always ended up doing this with using size_t[2] or size_t[3] (for slicing with strides) when I've coded Nd-arrays, though this is a bit clunky. However, a while ago someone mentioned that tuple, though cool/useful/etc wasn't being used as much (compared to other languages) because of a lack of syntactic sugar. Which gave me the idea of using the .. operator to be syntactic sugar for tuple, as it would solve two birds with one stone. (Maybe three, if you count MVR)

Also needed is an extension of the opDollar to return different values based on the index:
opDollar(size_t index);

P.S. There's also at least one template bug blocking Nd-arrays and small vector types: (http://d.puremagic.com/issues/show_bug.cgi?id=2257).
P.S.S. Another template issue is that templating both opX and opX_r generally results in an overload conflict.
October 13, 2009
On Tue, Oct 13, 2009 at 10:22 AM, JC <jcrapuchettes@gmail.com> wrote:
> This idea along with a slice overload would save me a lot of pain and
> performance while working with matrices in my production code. Any ideas
> when this could be implemented in D1?
> Jonathan


It won't be implemented in D1.  Stability -- it's the beauty and the beast of D1.

--bb
October 13, 2009
On Tue, 13 Oct 2009 13:08:59 -0400, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:

> Bill Baxter wrote:
>> Huh? It didn't sound to me like it would get rid of anything, except
>> for the use of the word "index" in many methods that have to do with
>> index operations.  That just seems confusing to me.   I think the
>> opIndexXxxAssign functions may need to be added, but adding them by
>> overloading existing names doesn't seem a win to me.
>>  --bb
>
> That's a good point. But something is inherently problematic about name explosion (In the proposed solution there is still an explosion in the count of functions that need to be written.)
>
> Now I realize there's also a need for opSliceXxxAssign, bleh. Unless we ascribe a distinct type to a .. b.
>
>
> Andrei

A distinct type for a..b is needed to support the mixed slicing and index that occurs in Nd-array/Matrixes: i.e.
auto row0 = myMatrix[0,0..$];
October 13, 2009
Forgotten already?

http://prowiki.org/wiki4d/wiki.cgi?DocComments/Property#Semantic

This is the same problem as property lvalue-ness and it has the same solution.  When property rewriting is done correctly, the opIndexAssign problem can then be solved almost for free.

Just treat opIndex expressions as properties, and when they are the subject of a side-effect then make sure the write property (AKA opIndexAssign) gets called.
October 13, 2009
On Tue, Oct 13, 2009 at 8:56 AM, Don <nospam@nospam.com> wrote:
> 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 think it's a good start.

In the list of properties, you should probably mention that 'a' is a scalar.

But I wonder how the rules involving scalars could be enforced, given that it's possible to define new scalar types.  One would have to tell the compiler somehow which types are scalars relative to the type being defined.

The ++ operators don't make sense for many of the types you listed.
Maybe that should be broken out.  Actually three of the things really
stand out as computer-isms that don't really belong with the other
mathematical properties:
x@=y <==> x = x @ y
x++ <==> ++x
x@=y returns x

Also, you can add Clifford algebra, Grassmann algebra, and geometric algebra to the list of things where the mathematical properties hold.

--bb