digitalmars.D.learn - Why is opIndexAssign replaced by opSlice here?
- Elmar (31/31) Oct 17 2021 Hello Dear community.
- Elmar (3/3) Oct 17 2021 Btw, I should have written:
- Paul Backus (24/61) Oct 17 2021 What happens here is, the compiler first tries the D2-style
- Paul Backus (3/9) Oct 17 2021 https://issues.dlang.org/show_bug.cgi?id=22417
- Imperatorn (2/12) Oct 17 2021 Gold star for fixing broken examples 🌟
- Elmar (8/38) Oct 18 2021 Woow! You fixed the problem, it now works for me.
Hello Dear community. I'd like to overload `opIndexAssign` for a struct which wraps around a generic array (so that it can't support `opIndex` due to unknown return type). Broken down as much as possible this is the code: ``` import std.stdio : writeln; import std.range : ElementType; struct S { void opIndexAssign(X, RANGE)(X x, RANGE range) if (is(ElementType!RANGE : size_t)) { writeln(__FUNCTION__); } auto opSlice(size_t start, size_t end) { import std.range : iota; return iota(start, end); } } void main() { auto arr = new int[7]; S s; s.opIndexAssign(arr, s.opSlice(1,4)); // works s[0..3] = arr[1..4]; // does not work, compiles to `s.opSlice(0,3) = arr[1..4]` } ``` I'm clueless about why it wouldn't compile the last statement to `s.opIndexAssign(arr[1..4], s.opSlice(0,3))`. Help appreciated :-)
Oct 17 2021
Btw, I should have written: `s.opIndexAssign(arr[1..4], s.opSlice(0,3));` But it compiles the same way.
Oct 17 2021
On Sunday, 17 October 2021 at 22:52:27 UTC, Elmar wrote:Hello Dear community. I'd like to overload `opIndexAssign` for a struct which wraps around a generic array (so that it can't support `opIndex` due to unknown return type). Broken down as much as possible this is the code: ``` import std.stdio : writeln; import std.range : ElementType; struct S { void opIndexAssign(X, RANGE)(X x, RANGE range) if (is(ElementType!RANGE : size_t)) { writeln(__FUNCTION__); } auto opSlice(size_t start, size_t end) { import std.range : iota; return iota(start, end); } } void main() { auto arr = new int[7]; S s; s.opIndexAssign(arr, s.opSlice(1,4)); // works s[0..3] = arr[1..4]; // does not work, compiles to `s.opSlice(0,3) = arr[1..4]` } ``` I'm clueless about why it wouldn't compile the last statement to `s.opIndexAssign(arr[1..4], s.opSlice(0,3))`. Help appreciated :-)What happens here is, the compiler first tries the D2-style rewrite: ```d s.opIndexAssign(arr[1..4], s.opSlice!0(0, 3)) ``` However, that rewrite fails to compile, because your `opSlice` does not take a template argument specifying the dimension along which to slice, as specified in the language spec's section on ["Slice Operator Overloading".][1] Since the above rewrite fails to compile, it falls back to rewriting the expression using D1-style operator overloads:For backward compatibility, `a[]` and `a[i..j]` can also be overloaded by implementing `opSlice()` with no arguments and `opSlice(i, j)` with two arguments, respectively. This only applies for one-dimensional slicing, and dates from when D did not have full support for multidimensional arrays. This usage of opSlice is discouraged....which results in the following rewritten statement: ```d s.opSlice(0, 3) = arr[1..4]; ``` My guess is that you got into this situation by trying to follow the example in the spec's section on ["Slice Assignment Operator Overloading"][2]. Unfortunately, that example is incorrect. Here is a fixed version of your example on run.dlang.io: https://run.dlang.io/is/dtfT5y [1]: https://dlang.org/spec/operatoroverloading.html#slice [2]: https://dlang.org/spec/operatoroverloading.html#slice_assignment_operator
Oct 17 2021
On Monday, 18 October 2021 at 03:42:35 UTC, Paul Backus wrote:My guess is that you got into this situation by trying to follow the example in the spec's section on ["Slice Assignment Operator Overloading"][2]. Unfortunately, that example is incorrect. [2]: https://dlang.org/spec/operatoroverloading.html#slice_assignment_operatorhttps://issues.dlang.org/show_bug.cgi?id=22417 https://github.com/dlang/dlang.org/pull/3113
Oct 17 2021
On Monday, 18 October 2021 at 04:11:18 UTC, Paul Backus wrote:On Monday, 18 October 2021 at 03:42:35 UTC, Paul Backus wrote:Gold star for fixing broken examples 🌟My guess is that you got into this situation by trying to follow the example in the spec's section on ["Slice Assignment Operator Overloading"][2]. Unfortunately, that example is incorrect. [2]: https://dlang.org/spec/operatoroverloading.html#slice_assignment_operatorhttps://issues.dlang.org/show_bug.cgi?id=22417 https://github.com/dlang/dlang.org/pull/3113
Oct 17 2021
On Monday, 18 October 2021 at 03:42:35 UTC, Paul Backus wrote:What happens here is, the compiler first tries the D2-style rewrite: ```d s.opIndexAssign(arr[1..4], s.opSlice!0(0, 3)) ``` However, that rewrite fails to compile, because your `opSlice` does not take a template argument specifying the dimension along which to slice, as specified in the language spec's section on ["Slice Operator Overloading".][1] Since the above rewrite fails to compile, it falls back to rewriting the expression using D1-style operator overloads:Woow! You fixed the problem, it now works for me. I wish the compiler would have been able to make me understand the problem. It was no help because it only tells the final erroneous consequence, that the return value of `opSlice` cannot be assigned ("is no lvalue", beginner-unfriendly language). It doesn't even mention `opSlice` or the fallback (reason) with no warning.For backward compatibility, `a[]` and `a[i..j]` can also be overloaded by implementing `opSlice()` with no arguments and `opSlice(i, j)` with two arguments, respectively. This only applies for one-dimensional slicing, and dates from when D did not have full support for multidimensional arrays. This usage of opSlice is discouraged....which results in the following rewritten statement: ```d s.opSlice(0, 3) = arr[1..4]; ``` My guess is that you got into this situation by trying to follow the example in the spec's section on ["Slice Assignment Operator Overloading"][2]. Unfortunately, that example is incorrect. Here is a fixed version of your example on run.dlang.io: https://run.dlang.io/is/dtfT5y [1]: https://dlang.org/spec/operatoroverloading.html#slice [2]: https://dlang.org/spec/operatoroverloading.html#slice_assignment_operator
Oct 18 2021