Thread overview
reference return values
May 08, 2004
Frank Fischer
May 08, 2004
J Anderson
May 08, 2004
Frank Fischer
May 08, 2004
hellcatv
May 08, 2004
Mike Wynn
May 09, 2004
J Anderson
May 09, 2004
Frank Fischer
May 09, 2004
Juan C
May 09, 2004
Frank Fischer
May 08, 2004
Hi,

is there any way in D to return references to values (e.g. member variables of an object), like this in C++:

class Matrix {
private:
double* data;

public:
..
double& at(int i, int j) { return data[i + j*rows]; }
..
double& operator()(int i, int j) { return at(i,j); }
}


Thin one can use this class like this as lvalue:

Matrix m(10,10);
m.at(1,1) = 1.0;
/* or with operators: */
m(1,1) = 1.0;

One can see the two problems here: you need reference return values (or some
equivalent syntax sugar) to use functions with more than zero parameters as
lvalues (properties only work without parameters).
For this special problem it would perhaps be possible to overload the array []
operator, but this can only be done with one single operator (that's the reason
for using the call operator () in C++).

I want to port some of my matrix-classes to D, and therefore something like this would be nice.


May 08, 2004
Frank Fischer wrote:

>Hi,
>
>is there any way in D to return references to values (e.g. member variables of
>an object), like this in C++:
>
>class Matrix {
>private:
>double* data;
>
>public:
>..
>double& at(int i, int j) { return data[i + j*rows]; }
>..
>double& operator()(int i, int j) { return at(i,j); }
>} 
>
>
>Thin one can use this class like this as lvalue:
>
>Matrix m(10,10);
>m.at(1,1) = 1.0;
>/* or with operators: */
>m(1,1) = 1.0;
>
>One can see the two problems here: you need reference return values (or some
>equivalent syntax sugar) to use functions with more than zero parameters as
>lvalues (properties only work without parameters). For this special problem it would perhaps be possible to overload the array []
>operator, but this can only be done with one single operator (that's the reason
>for using the call operator () in C++).
>
>I want to port some of my matrix-classes to D, and therefore something like this
>would be nice.
>

You can use more then one [][] using a proxy object:  This is something I posted before.  You'll need to work it into your own problem.

Most of the overhead would be optimised away.

struct Col
{
  private int [][] array;
    private int i;
    static Col opCall(int [][]array, int pos)
  {
      Col col;
      col.array = array;
      col.i = pos;
      return col;
  }
    int opIndex(int j) { return array[i][j]; }
    int opIndex(int j, int value) { return array[i][j] = value; }
    void length(int len) { array.length = len; }
}

class Array
{
  private int [][] array;
    this(int size, int size2)
  {
      array.length = size;
            foreach ( inout  int [] arr; array)
          arr.length = size2;
  }
    Col opIndex(int i)
  {
      return Col(array, i);    }
}


int main (char[][] args)
{
      Array a = new Array(10,10);

      a[1][0] = 5;
      a[1][1] = 6;
            printf("a[1][0] = %d\n", a[1][0]);
            printf("a[1][1] = %d\n", a[1][1]);

      return 0;
}


-- 
-Anderson: http://badmama.com.au/~anderson/
May 08, 2004
In article <c7is2l$1arh$1@digitaldaemon.com>, J Anderson says...
>
>You can use more then one [][] using a proxy object:  This is something I posted before.  You'll need to work it into your own problem.
>
>Most of the overhead would be optimised away.
>

Well, but that's not more than a workaround. The problem now is what to do, if i need both, a two-parameter operator (for matrix-like access) _and_ a one-parameter operator (for vector-like access) in one class? I cannot use the []-operator for both. And _most_ of the overhead is not _all_, and that's sth I don't like, because speed is an important factor in my case.

Furthermore, i think "m(1,2)" or "m[1,2]" looks nicer than "m[1][2]" ;)


May 08, 2004
can you overload opCall for this (if it's a struct at least)


In article <c7jaoc$21nt$1@digitaldaemon.com>, Frank Fischer says...
>
>In article <c7is2l$1arh$1@digitaldaemon.com>, J Anderson says...
>>
>>You can use more then one [][] using a proxy object:  This is something I posted before.  You'll need to work it into your own problem.
>>
>>Most of the overhead would be optimised away.
>>
>
>Well, but that's not more than a workaround. The problem now is what to do, if i need both, a two-parameter operator (for matrix-like access) _and_ a one-parameter operator (for vector-like access) in one class? I cannot use the []-operator for both. And _most_ of the overhead is not _all_, and that's sth I don't like, because speed is an important factor in my case.
>
>Furthermore, i think "m(1,2)" or "m[1,2]" looks nicer than "m[1][2]" ;)
>
>


May 08, 2004
On Sat, 8 May 2004 19:00:28 +0000 (UTC), Frank Fischer
<Frank_member@pathlink.com> wrote:

>In article <c7is2l$1arh$1@digitaldaemon.com>, J Anderson says...
>>
>>You can use more then one [][] using a proxy object:  This is something I posted before.  You'll need to work it into your own problem.
>>
>>Most of the overhead would be optimised away.
>>
>
>Well, but that's not more than a workaround. The problem now is what to do, if i need both, a two-parameter operator (for matrix-like access) _and_ a one-parameter operator (for vector-like access) in one class? I cannot use the []-operator for both. And _most_ of the overhead is not _all_, and that's sth I don't like, because speed is an important factor in my case.
>
>Furthermore, i think "m(1,2)" or "m[1,2]" looks nicer than "m[1][2]" ;)
>
some time ago I posted this example
opCall return an int *
so b[y][x] = v => *b(x, y) = v;
so v = b[y][x] = => v = *b(x, y);

----------------------

import std.c.stdio;

class B {
	int[] data;
	int lw;
	 this( int xw, int yw ) { lw = xw; data=new int[xw*yw]; }
	 int[] opCall( int y ) { return this[y]; }
	 int *  opCall( int x, int y ) { return &data[(y*lw)+x]; }
	 int[] opIndex( int y ) { return data[(y*lw)..((y*lw)+lw)]; }
	void dump() {
		printf( "data [" ); foreach( int v; data ) { printf(
"%d, ", v ); }
		printf( "]\n" );
	}
}

int main( char[][] argv ) {
	B b = new B( 2, 2 );
	int[] ar = b[0];
	printf("ar.length:%d\n", ar.length);
	ar[0] = 1; ar[1] = 2;
	*(b(1,1)) =3;
	*(b(0,1)) =-4;
	b.dump();

	return 1;
}
------------------------
I though about having opCall return a struct that overloaded
opCatAssign as there is no overloaded opAssign (that I've found)
thus
struct Element {
	int * ptr;
	Element opCatAssign( int i ) { *ptr = i; return *this; }
	int value() { return *ptr; }
}
class B {
 ... as about except ....
	 Element  opCall( int x, int y ) {
	 	Element rv;
	 	rv.ptr = &data[(y*lw)+x];
	 	return rv;
	}
}
int main( char[][] argv ) {
	B b = new B( 2, 2 );
	int[] ar = b[0];
	printf("ar.length:%d\n", ar.length);
	ar[0] = 1; ar[1] = 2;
	b(1,1) ~= 3;
	b(0,1) ~= -4;
	b.dump();

	return 1;
}

more overhead for little improvement, still think D needs true rectangular arrays in the form [n,m] etc. like c#.

Mike.

May 09, 2004
<snip>
>m.at(1,1) = 1.0;
>/* or with operators: */
>m(1,1) = 1.0;
</snip>

M m = new M(1.0);

would be clearer, no?


May 09, 2004
On 2004-05-09, Juan C <Juan_member@pathlink.com> wrote:
><snip>
>>m.at(1,1) = 1.0;
>>/* or with operators: */
>>m(1,1) = 1.0;
></snip>
>
> M m = new M(1.0);
>
> would be clearer, no?
No, m(1,1) should be an access to a member-field of M, not the creation
of a new object.

May 09, 2004
Frank Fischer wrote:

>In article <c7is2l$1arh$1@digitaldaemon.com>, J Anderson says...
>  
>
>>You can use more then one [][] using a proxy object:  This is something I posted before.  You'll need to work it into your own problem.
>>
>>Most of the overhead would be optimised away.
>>
>>    
>>
>
>Well, but that's not more than a workaround. 
>
It's the way you'd do it in C++ as well.

>The problem now is what to do, if i
>need both, a two-parameter operator (for matrix-like access) _and_ a
>one-parameter operator (for vector-like access) in one class? I cannot use the
>[]-operator for both. And _most_ of the overhead is not _all_, and that's sth I
>don't like, because speed is an important factor in my case.
>
>Furthermore, i think "m(1,2)" or "m[1,2]" looks nicer than "m[1][2]" ;)
>  
>

Using the way I suggested is quite powerful because you can control each dimension of the array ie:

A[x].length = 10;
A[x][y].length = 10;

Also if you want to use the array for more then one thing, simply create a new class to do it and then call it by method using something like this:

A.reverse[x][y] ...

-- 
-Anderson: http://badmama.com.au/~anderson/
May 09, 2004
On 2004-05-09, J Anderson <REMOVEanderson@badmama.com.au> wrote:
>>The problem now is what to do, if i
>>need both, a two-parameter operator (for matrix-like access) _and_ a
>>one-parameter operator (for vector-like access) in one class? I cannot use the
>>[]-operator for both. And _most_ of the overhead is not _all_, and that's sth I
>>don't like, because speed is an important factor in my case.
>>
>>Furthermore, i think "m(1,2)" or "m[1,2]" looks nicer than "m[1][2]" ;)
>> 
>>
>
> Using the way I suggested is quite powerful because you can control each dimension of the array ie:
>
> A[x].length = 10;
> A[x][y].length = 10;
>
> Also if you want to use the array for more then one thing, simply create a new class to do it and then call it by method using something like this:
>
> A.reverse[x][y] ...
>
This could be usefull for arrays, but I don't talk about arrays. I mean
matrices in the mathematical sense. So there's no need for controlling
each dimension of subarrays. And I think it's strange to access elements
of a matrix like this:
A.matrix[i][j]
A.vector[i]
...

Wouldn't it be nicer to do it that way:
A(i,j) and
A(i)

Of course, returning pointers could be a way out (as mentioned in another posting by someone), but I think that's not the way someone using this matrix-class would expect. And as always, something unexpected is a potential source of trouble.