Thread overview
Struct array assignment behaviour using example from Programming in D, chapter 78
Mar 24, 2016
data pulverizer
Mar 24, 2016
data pulverizer
Mar 24, 2016
Ali Çehreli
Mar 25, 2016
data pulverizer
Mar 25, 2016
Ali Çehreli
Mar 25, 2016
data pulverizer
March 24, 2016
I have been playing with the matrix example given at the end of chapter 78 of Ali Çehreli's fabulous book and am having problems with overloading the opAssign operator.

rows is a private int[][] in a Matrix struct.

I have added the following ...

Matrix opAssign(int[][] arr)
{
    this.rows = arr;
    // rows = arr // does not work either ...
    return this;
}

However this does not work (no error occurs, it just doesn't do anything) but this does work ...

Matrix opAssign(int[][] arr)
{
    foreach(i, row; rows){
        row[] = arr[i];
    }
    return this;
}

The second is not efficient since it has to loop to assign the array. Is there a more efficient way of overwriting the array?

March 24, 2016
On Thursday, 24 March 2016 at 17:24:38 UTC, data pulverizer wrote:
> I have been playing with the matrix example given at the end of chapter 78 of Ali Çehreli's fabulous book and am having problems with overloading the opAssign operator.
>
> rows is a private int[][] in a Matrix struct.
>
> I have added the following ...
>
> Matrix opAssign(int[][] arr)
> {
>     this.rows = arr;
>     // rows = arr // does not work either ...
>     return this;
> }
>
> However this does not work (no error occurs, it just doesn't do anything) but this does work ...
>
> Matrix opAssign(int[][] arr)
> {
>     foreach(i, row; rows){
>         row[] = arr[i];
>     }
>     return this;
> }
>
> The second is not efficient since it has to loop to assign the array. Is there a more efficient way of overwriting the array?

Sorry. Please disregard. I'll drive home and ask this question properly!
March 24, 2016
On 03/24/2016 10:24 AM, data pulverizer wrote:
> I have been playing with the matrix example given at the end of chapter
> 78 of Ali Çehreli's

For reference, it's "Multi-dimensional operator overloading example" here:

  http://ddili.org/ders/d.en/templates_more.html

>having problems with overloading the opAssign operator.
>
> rows is a private int[][] in a Matrix struct.
>
> I have added the following ...
>
> Matrix opAssign(int[][] arr)
> {
>      this.rows = arr;
>      // rows = arr // does not work either ...
>      return this;
> }
>
> However this does not work (no error occurs, it just doesn't do
> anything)

How are you testing it? The following worked for me:

1) Added that opAssign() to the struct. (Verified that it gets called.)

2) Tested with the following code:

    auto m2 = Matrix();
    auto rows = [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ];
    m2 = rows;

    writeln(m2);

(I've tested with a dynamically generated 'rows' as well.)

Ali

March 25, 2016
On Thursday, 24 March 2016 at 18:46:14 UTC, Ali Çehreli wrote:
> On 03/24/2016 10:24 AM, data pulverizer wrote:
> > I have been playing with the matrix example given at the end
> of chapter
> > 78 of Ali Çehreli's
>
> For reference, it's "Multi-dimensional operator overloading example" here:
>
>   http://ddili.org/ders/d.en/templates_more.html
>
> >having problems with overloading the opAssign operator.
> >
> > rows is a private int[][] in a Matrix struct.
> >
> > I have added the following ...
> >
> > Matrix opAssign(int[][] arr)
> > {
> >      this.rows = arr;
> >      // rows = arr // does not work either ...
> >      return this;
> > }
> >
> > However this does not work (no error occurs, it just doesn't
> do
> > anything)
>
> How are you testing it? The following worked for me:
>
> 1) Added that opAssign() to the struct. (Verified that it gets called.)
>
> 2) Tested with the following code:
>
>     auto m2 = Matrix();
>     auto rows = [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ];
>     m2 = rows;
>
>     writeln(m2);
>
> (I've tested with a dynamically generated 'rows' as well.)
>
> Ali

Thank you. Let me try to ask the question again. The problem I am experiencing is to do with opIndexAssign().

I added the following public operators:

	Matrix opAssign(int[][] arr)
	{
		writeln(__FUNCTION__);
		this.rows = arr;
		return this;
	}

	Matrix opAssign(Matrix mat)
	{
		writeln(__FUNCTION__);
		this.rows = mat.rows;
		return this;
	}

	Matrix opIndexAssign(A...)(int[][] arr, A arguments)
		if(A.length <= 2){
		writeln(__FUNCTION__);
		Matrix subMatrix = opIndex(arguments);
		assert(((arr.length == subMatrix.nrow()) & (arr[0].length == subMatrix.ncol())),
			"Array dimension do not match matrix replacement.\n");
		/*foreach(i, row; subMatrix.rows){
			row[] = arr[i];
		}*/
		subMatrix = arr; // Does not work
		return subMatrix;
	}

	Matrix opIndexAssign(A...)(Matrix mat, A arguments)
	if(A.length <= 2){
		writeln(__FUNCTION__);
		Matrix subMatrix = opIndex(arguments);
		assert(((mat.nrow() == subMatrix.nrow()) & (mat.ncol() == subMatrix.ncol())),
		"Array dimension do not match matrix replacement.\n");
		/*foreach(i, row; subMatrix.rows){
			row[] = mat.rows[i];
		}*/
		subMatrix = mat; // Does not work
		return subMatrix;
	}




void main(){
	// Here we test opAssign [][]int
	auto a = Matrix();
	a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; // this works
	writeln(a);
	// opIndexAssign int[][]
	a[0..2, 0..2] = [[88, 88], [88, 88]]; // this does not work
	writeln(a);
	auto b = Matrix();
	// opAssign Matrix
	b = a; // this works
	writeln(b);
	b = [[88, 88, 88, 88], [88, 88, 88, 88], [88, 88, 88, 88], [88, 88, 88, 88]];
	// opIndexAssign Matrix
	b[0..3, 0..3] = a; // this does not work
	writeln(b);
}


If you uncomment the foreach lines, the opIndexAssign() work.

March 25, 2016
On 03/25/2016 12:00 AM, data pulverizer wrote:
> On Thursday, 24 March 2016 at 18:46:14 UTC, Ali Çehreli wrote:
>> On 03/24/2016 10:24 AM, data pulverizer wrote:
>> > I have been playing with the matrix example given at the end
>> of chapter
>> > 78 of Ali Çehreli's
>>
>> For reference, it's "Multi-dimensional operator overloading example"
>> here:
>>
>>   http://ddili.org/ders/d.en/templates_more.html
>>
>> >having problems with overloading the opAssign operator.

> Thank you. Let me try to ask the question again. The problem I am
> experiencing is to do with opIndexAssign().
>
> I added the following public operators:
>
>      Matrix opAssign(int[][] arr)
>      {
>          writeln(__FUNCTION__);
>          this.rows = arr;
>          return this;
>      }

The problem is due to the aliasing of 'rows' members of Matrix objects. subMatrix is supposed to be a reference into some elements of an existing Matrix. As soon as we do the above assignment, this Matrix (which may be a subMatrix in a specific context) breaks lose from its actual Matrix elements.

We need to implement the function above "in place":

    Matrix opAssign(int[][] arr)
    {
        writeln(__FUNCTION__);

        if (rows.length < arr.length) {
            rows.length = arr.length;
        }

        foreach (i, row; arr) {
            const newLength = row.length;

            if (rows[i].length < newLength) {
                rows[i].length = newLength;
            }
            rows[i][0..newLength] = row[];
        }

        return this;
    }

(There must be an existing function that does that.)

>      Matrix opAssign(Matrix mat)
>      {
>          writeln(__FUNCTION__);
>          this.rows = mat.rows;

Same thing applies above: We need to assign to this.rows in place (which is easier by taking advantage of the previous function):

        this = mat.rows;

>          return this;
>      }

No changes needed for the other two functions but I would 'return this' instead of 'return subMatrix' for them as well.

Ali

March 25, 2016
On Friday, 25 March 2016 at 08:53:20 UTC, Ali Çehreli wrote:
> On 03/25/2016 12:00 AM, data pulverizer wrote:
> > On Thursday, 24 March 2016 at 18:46:14 UTC, Ali Çehreli wrote:
> >> On 03/24/2016 10:24 AM, data pulverizer wrote:
> >> > I have been playing with the matrix example given at the
> end
> >> of chapter
> >> > 78 of Ali Çehreli's
> >>
> >> For reference, it's "Multi-dimensional operator overloading
> example"
> >> here:
> >>
> >>   http://ddili.org/ders/d.en/templates_more.html
> >>
> >> >having problems with overloading the opAssign operator.
>
> > Thank you. Let me try to ask the question again. The problem
> I am
> > experiencing is to do with opIndexAssign().
> >
> > I added the following public operators:
> >
> >      Matrix opAssign(int[][] arr)
> >      {
> >          writeln(__FUNCTION__);
> >          this.rows = arr;
> >          return this;
> >      }
>
> The problem is due to the aliasing of 'rows' members of Matrix objects. subMatrix is supposed to be a reference into some elements of an existing Matrix. As soon as we do the above assignment, this Matrix (which may be a subMatrix in a specific context) breaks lose from its actual Matrix elements.
>
> We need to implement the function above "in place":
>
>     Matrix opAssign(int[][] arr)
>     {
>         writeln(__FUNCTION__);
>
>         if (rows.length < arr.length) {
>             rows.length = arr.length;
>         }
>
>         foreach (i, row; arr) {
>             const newLength = row.length;
>
>             if (rows[i].length < newLength) {
>                 rows[i].length = newLength;
>             }
>             rows[i][0..newLength] = row[];
>         }
>
>         return this;
>     }
>
> (There must be an existing function that does that.)
>
> >      Matrix opAssign(Matrix mat)
> >      {
> >          writeln(__FUNCTION__);
> >          this.rows = mat.rows;
>
> Same thing applies above: We need to assign to this.rows in place (which is easier by taking advantage of the previous function):
>
>         this = mat.rows;
>
> >          return this;
> >      }
>
> No changes needed for the other two functions but I would 'return this' instead of 'return subMatrix' for them as well.
>
> Ali

That's great! Thank you very much for the fix and extra suggestions, and for your patience putting up with my poorly formulated question! Looks like I need to go and read all the structs and operators chapters thoroughly!