www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Getting a working example of opIndexAssign using opSlice ... have

reply james.p.leblanc <james.p.leblanc gmail.com> writes:
Greetings,

I have been trying to get a working example of slice assignment 
operator
overloading ... and am befuddled.  From the spec (section 
20.6.2), the
code below appears:

     struct A
     {
         int opIndexAssign(int v);  // overloads a[] = v
         int opIndexAssign(int v, size_t[2] x);  // overloads a[i 
.. j] = v
         int[2] opSlice(size_t x, size_t y);     // overloads i .. 
j
     }

     void test()
     {
         A a;
         int v;

         a[] = v;  // same as a.opIndexAssign(v);
         a[3..4] = v;  // same as a.opIndexAssign(v, 
a.opSlice(3,4));
     }

I have hacked at this trying to get a simple working example.  
Could
anyone guide me here please?

Best Regards,
James
Aug 15 2021
next sibling parent reply Bastiaan Veelo <Bastiaan Veelo.net> writes:
On Sunday, 15 August 2021 at 20:41:51 UTC, james.p.leblanc wrote:
     struct A
     {
         int opIndexAssign(int v);  // overloads a[] = v
         int opIndexAssign(int v, size_t[2] x);  // overloads 
 a[i .. j] = v
         int[2] opSlice(size_t x, size_t y);     // overloads i 
 .. j
     }

     void test()
     {
         A a;
         int v;

         a[] = v;  // same as a.opIndexAssign(v);
         a[3..4] = v;  // same as a.opIndexAssign(v, 
 a.opSlice(3,4));
     }

 I have hacked at this trying to get a simple working example.
Not sure if this does enough of what you’re looking for, but this covers the minimal steps to get it working: https://run.dlang.io/is/m5svQ2 ```d import std; struct A { int opIndexAssign(int v) // overloads a[] = v { writeln(__FUNCTION__); return 42; } int opIndexAssign(int vh, size_t[2] x) // overloads a[i .. j] = v { writeln(__FUNCTION__); return 43; } int[2] opSlice(size_t x, size_t y) // overloads i .. j { writeln(__FUNCTION__); return [44, 45]; } } void main() { A a; int v; a[] = v; // same as a.opIndexAssign(v); a[3..4] = v; // same as a.opIndexAssign(v, a.opSlice(3,4)); } ``` — Bastiaan.
Aug 15 2021
parent reply james.p.leblanc <james.p.leblanc gmail.com> writes:
On Sunday, 15 August 2021 at 21:15:02 UTC, Bastiaan Veelo wrote:
 On Sunday, 15 August 2021 at 20:41:51 UTC, james.p.leblanc
 — Bastiaan.
Bastiaan, Thanks kindly for your response! Unfortunately, I do not see what the program does. I mean A is a structure that has only functions. So, how are any elements of this being set to the value of v? I tried extending the code mentioned by adding a member array, but no luck. I often have difficulties to understand the notations used in the spec, and only sometimes can I extend them to working examples. Would it be possible to add the last couple of details regarding an array member? I attempted but the values always remain zero even when I set v=4. import std; struct A { int[5] a; int opIndexAssign(int v) // overloads a[] = v { writeln(__FUNCTION__); return 42; } int opIndexAssign(int vh, size_t[2] x) // overloads a[i .. j] = v { writeln(__FUNCTION__); return 43; } int[2] opSlice(size_t x, size_t y) // overloads i .. j { writeln(__FUNCTION__); return [44, 45]; } } void main() { A a; int v=4; writeln(a); a[] = v; // same as a.opIndexAssign(v); writeln(a); a[3..4] = v; // same as a.opIndexAssign(v, a.opSlice(3,4)); writeln(a); } Thanks once again, James
Aug 15 2021
parent james.p.leblanc <james.p.leblanc gmail.com> writes:
On Sunday, 15 August 2021 at 21:28:53 UTC, james.p.leblanc wrote:
 On Sunday, 15 August 2021 at 21:15:02 UTC, Bastiaan Veelo wrote:
 On Sunday, 15 August 2021 at 20:41:51 UTC, james.p.leblanc
 — Bastiaan.
Bastiaan, Thanks once again, James
On Sunday, 15 August 2021 at 21:28:53 UTC, james.p.leblanc wrote: Okay! Great! Thanks everyone Bastiaan, ag0aep6g, and russhy ... I see more replies come in while I was typing. There is some excellent information here that I need to digest. I believe that I have what I need. This group has been great! BR, James
Aug 15 2021
prev sibling next sibling parent reply ag0aep6g <anonymous example.com> writes:
On Sunday, 15 August 2021 at 20:41:51 UTC, james.p.leblanc wrote:
 I have been trying to get a working example of slice assignment 
 operator
 overloading ... and am befuddled.  From the spec (section 
 20.6.2), the
 code below appears:

     struct A
     {
         int opIndexAssign(int v);  // overloads a[] = v
         int opIndexAssign(int v, size_t[2] x);  // overloads 
 a[i .. j] = v
         int[2] opSlice(size_t x, size_t y);     // overloads i 
 .. j
     }

     void test()
     {
         A a;
         int v;

         a[] = v;  // same as a.opIndexAssign(v);
         a[3..4] = v;  // same as a.opIndexAssign(v, 
 a.opSlice(3,4));
     }
I have no experience with this, but from a cursory look it seems that that example is wrong. For starters, the type of `opIndexAssign`'s second parameter must match the return type of `opSlice`. This is easily fixed, but the code still doesn't work. Further down on the spec page [1], there is this little table: | op | rewrite | |-----------------------|------------------------------------------------------| | `arr[1, 2..3, 4] = c` | `arr.opIndexAssign(c, 1, arr.opSlice!1(2, 3), 4)` | | `arr[2, 3..4] += c` | `arr.opIndexOpAssign!"+"(c, 2, arr.opSlice!1(2, 3))` | Note the `!1` on `opSlice`. So you need to make `opSlice` a template with an integer parameter. Working example: ```d import std.stdio; struct A { int opIndexAssign(int v, size_t[2] x) { writeln("opIndexAssign: ", v, ", ", x); return v; } size_t[2] opSlice(size_t i)(size_t x, size_t y) { return [x, y]; } } void main() { A a; int v = 42; a[3..4] = v; /* Prints "opIndexAssign: 42, [3, 4]". */ } ``` [1] https://dlang.org/spec/operatoroverloading.html#slice
Aug 15 2021
parent russhy <russhy gmail.com> writes:
There is an example here:

http://www.rosettacode.org/wiki/Multi-dimensional_array#D

Look at the Matrix struct
Aug 15 2021
prev sibling parent reply Tejas <notrealemail gmail.com> writes:
On Sunday, 15 August 2021 at 20:41:51 UTC, james.p.leblanc wrote:
 Greetings,

 I have been trying to get a working example of slice assignment 
 operator
 overloading ... and am befuddled.  From the spec (section 
 20.6.2), the
 code below appears:

     struct A
     {
         int opIndexAssign(int v);  // overloads a[] = v
         int opIndexAssign(int v, size_t[2] x);  // overloads 
 a[i .. j] = v
         int[2] opSlice(size_t x, size_t y);     // overloads i 
 .. j
     }

     void test()
     {
         A a;
         int v;

         a[] = v;  // same as a.opIndexAssign(v);
         a[3..4] = v;  // same as a.opIndexAssign(v, 
 a.opSlice(3,4));
     }

 I have hacked at this trying to get a simple working example.  
 Could
 anyone guide me here please?

 Best Regards,
 James
If you're finding the spec too hard, please try Ali's book. I'm sharing the part on operator overloading below: http://ddili.org/ders/d.en/operator_overloading.html Please ping if you still have problems; I'll then write a full program.
Aug 15 2021
parent reply james.p.leblanc <james.p.leblanc gmail.com> writes:
On Monday, 16 August 2021 at 05:26:00 UTC, Tejas wrote:

 If you're finding the spec too hard, please try Ali's book. I'm 
 sharing the part on operator overloading below:

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

 Please ping if you still have problems; I'll then write a full 
 program.
Hej Tejas! Thanks for your message. I have it working now. Yes, Ali's book is a tremendously good reference. But, I had trouble digging out the "magic sauce" from the pages to get this working. I was able to find the sauce in a forum post by Adam Ruppe (his book is also an excellent place for ideas and code). With "opCast", my difficulty was the description of the type I wish to cast to uses a colon ":". Here is the line that allows it to function as desired: **>> T[] opCast(T : T[])(){... }** Best Regards, jpl
Aug 15 2021
parent reply Tejas <notrealemail gmail.com> writes:
On Monday, 16 August 2021 at 06:12:42 UTC, james.p.leblanc wrote:
 On Monday, 16 August 2021 at 05:26:00 UTC, Tejas wrote:

 If you're finding the spec too hard, please try Ali's book. 
 I'm sharing the part on operator overloading below:

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

 Please ping if you still have problems; I'll then write a full 
 program.
Hej Tejas! Thanks for your message. I have it working now. Yes, Ali's book is a tremendously good reference. But, I had trouble digging out the "magic sauce" from the pages to get this working. I was able to find the sauce in a forum post by Adam Ruppe (his book is also an excellent place for ideas and code). With "opCast", my difficulty was the description of the type I wish to cast to uses a colon ":". Here is the line that allows it to function as desired: **>> T[] opCast(T : T[])(){... }** Best Regards, jpl
Maybe just write `T[]` in code rather than making it happen via the colon? I also have similar troubles, removing the default value always helped me. Can you show the code where you're trying to apply this?
Aug 15 2021
parent reply james.p.leblanc <james.p.leblanc gmail.com> writes:
On Monday, 16 August 2021 at 06:20:11 UTC, Tejas wrote:

 Maybe just write `T[]` in code rather than making it happen via 
 the colon?

 I also have similar troubles, removing the default value always 
 helped me.

 Can you show the code where you're trying to apply this?
Hej Tejas, Sure, here is the code snippet, it resides within a struct along with various operator overloads. To be honest, I am not exactly sure what is happening here. I am unfamiliar with the "(T : T[])" syntax ... need to read up a bit on that. (However, not so eary searching for a ":") BR, jpl // --- cast overloading ------------------------------------------- // T[] opCast(T : T[])(){ // this works T[] opCast(T[])(){ // yields: "Error: identifier expected for template value param" T[] x; x.length = this.length; for( int i = 0 ; i< this.length ; i++){ x[i] = this.ptr[i]; } return x; }
Aug 15 2021
next sibling parent reply Tejas <notrealemail gmail.com> writes:
On Monday, 16 August 2021 at 06:36:02 UTC, james.p.leblanc wrote:
 On Monday, 16 August 2021 at 06:20:11 UTC, Tejas wrote:

 Maybe just write `T[]` in code rather than making it happen 
 via the colon?

 I also have similar troubles, removing the default value 
 always helped me.

 Can you show the code where you're trying to apply this?
Hej Tejas, Sure, here is the code snippet, it resides within a struct along with various operator overloads. To be honest, I am not exactly sure what is happening here. I am unfamiliar with the "(T : T[])" syntax ... need to read up a bit on that. (However, not so eary searching for a ":") BR, jpl // --- cast overloading ------------------------------------------- // T[] opCast(T : T[])(){ // this works T[] opCast(T[])(){ // yields: "Error: identifier expected for template value param" T[] x; x.length = this.length; for( int i = 0 ; i< this.length ; i++){ x[i] = this.ptr[i]; } return x; }
Oh, you're writing `T[]` in the code anyways. I was saying to just remove the `:T[]` from the function parameter and write `T[]` in the function body itself, which you're already doing. If the code works, what's the problem?
Aug 15 2021
parent reply james.p.leblanc <james.p.leblanc gmail.com> writes:
On Monday, 16 August 2021 at 06:42:48 UTC, Tejas wrote:

 If the code works, what's the problem?
Hej Again, I was able to construct the working code shown above from help I obtained here in the forum and other resources. My original code was not working ... but updated code is working fine ... so there are no further problems. (Actually, I learned a fair amount in this endeavor!) Cheers! jpl
Aug 15 2021
parent Tejas <notrealemail gmail.com> writes:
On Monday, 16 August 2021 at 06:49:08 UTC, james.p.leblanc wrote:
 On Monday, 16 August 2021 at 06:42:48 UTC, Tejas wrote:

 If the code works, what's the problem?
Hej Again, I was able to construct the working code shown above from help I obtained here in the forum and other resources. My original code was not working ... but updated code is working fine ... so there are no further problems. (Actually, I learned a fair amount in this endeavor!) Cheers! jpl
Cool Just for completeness, here's what my solution looks like: ```d import std; struct S{ char[] a=['a','v','d']; T opCast(T)(){ return a.dup ; } } void main() { writeln("Hello D"); S s = S(); char[] d = cast(char[])s; } ```
Aug 15 2021
prev sibling parent reply Alexandru Ermicioi <alexandru.ermicioi gmail.com> writes:
On Monday, 16 August 2021 at 06:36:02 UTC, james.p.leblanc wrote:
 To be honest, I am not exactly sure what is happening here. I
 am unfamiliar with the "(T : T[])" syntax ... need to read
That is template argument secialization. You're saying that T can be accept only types that are arrays of T, where : reads as 'extends'. Now T : T[] might introduce cyclic reference, so more correct would be: foo(T : Z[], Z)(...) Here you say that T might accept only types that are arrays of Z elements. Regards, Alexandru.
Aug 16 2021
parent james.p.leblanc <james.p.leblanc gmail.com> writes:
On Monday, 16 August 2021 at 10:48:19 UTC, Alexandru Ermicioi 
wrote:
 On Monday, 16 August 2021 at 06:36:02 UTC, james.p.leblanc 
 wrote:
 To be honest, I am not exactly sure what is happening here. I
 am unfamiliar with the "(T : T[])" syntax ... need to read
That is template argument secialization. You're saying that T can be accept only types that are arrays of T, where : reads as 'extends'. Now T : T[] might introduce cyclic reference, so more correct would be: foo(T : Z[], Z)(...) Here you say that T might accept only types that are arrays of Z elements. Regards, Alexandru.
Alexandru, That is very helpful information. It also answers a nagging question I have been worried about. Specifically, that "T : T[]" bothered me even though I was unfamiliar with the syntax ... now I understand the situation better. Best Regards, James
Aug 16 2021