Easteregg: riddle of opIndex<op>Assign solved (nearly)

Manfred Nowak svv1999 at hotmail.com
Tue Feb 13 12:37:46 PST 2007


The solution uses chaining.

Let me show how to implement a class C that mimics a dynamic array, 
like "int[10] data" with _all_ possible "opIndex<op>Assign" 
overloads.

The usage of such a class should look like this

void main(){
  C a= new C;
  a[2]= 5;
  a[2]+= 3 ;
  writefln( a[2]); // prints 8
}

Here I restrict myself to the "opIndexAddAssign".

C holds a dynamic array "data". The length of this array is 
initialized by the constructor.

class C{
  int[] data;
  this( ulong len){
    data.length= len;
  }
}

To start chaining I need a static "opCall"    

class C{
  static C opCall(){
    return new C;
  }
}

To fetch the lvalue I use "opIndex", which stores the index 
temporarily:

class C{
  int index;
  C opIndex( int inx){
    index= inx;
    return this;
  }
}

To fetch the "opIndexAddAssign" I use "opAddAssign", which uses the 
temporarily stored lvalue index to assign to the correct position in 
the array:

class C{
  C opAddAssign(int p){
    data[ index]+= p;
    return this;
  }
}

That's it.

Drawbacks:
1) The natural rvalue "opIndex" is now used up for an lvalue 
"opIndex". Therefore a less natural opindex must be defined to return 
the natural "opIndex":

class C{
  int opIndex( int inx, int){
    return data[inx];
  }
}

A solution to avoid that additional parameter would be to let the 
compiler emit an "opEOM" on being unable to chain any further, which 
I have proposed a long time ago:
http://www.digitalmars.com/d/archives/26477.html

2) Chaining of assignments is not possible under this scheme.

-manfred

Full source:

import std.stdio;
class C{
    int[] data;
    this(int len){
      data.length= len;
    }
    static C opCall() {
      return new C(0);
    }
    int index;
    C opIndex( int inx){
      index= inx;
      return this;
    }
    int opIndex( int inx, int){
      return data[inx];
    }
    C opAddAssign(int p){
      data[ index]+= p;
      return this;
    }
    void opIndexAssign(int p, int x){
      data[ x]= p;
    }
}
void main(){
  C a= new C(10);
  a[2]= 5;
  a[2]+= 3 ;
  writefln( a[2 ,0]); // an ugly point
}



More information about the Digitalmars-d mailing list