digitalmars.dip.ideas - opIndexOpAssignOpDispatch
- monkyyy (7/7) Jun 14 ```d
- Basile B. (25/32) Jun 15 You can implement an opIndex overload that returns a struct that
- Quirin Schroll (44/77) Jun 17 ```d
- Basile B. (4/87) Jun 18 Nice. While the pattern was clear enough to be developped I'm
- Quirin Schroll (73/163) Jun 20 Copies are largely irrelevant. With `-dip1000`, the escaping
- Quirin Schroll (4/11) Jun 20 At this point, D would be getting close to a term language like
```d mystruct foo; foo[1337].isnull=true; ``` => `foo.opIndexOpAssignOpDispatch!"isnull"(1337,true)` it fits the naming scheme!
Jun 14
On Saturday, 15 June 2024 at 04:58:58 UTC, monkyyy wrote:```d mystruct foo; foo[1337].isnull=true; ``` => `foo.opIndexOpAssignOpDispatch!"isnull"(1337,true)` it fits the naming scheme!You can implement an opIndex overload that returns a struct that itself supports opDispatch. ```d struct Foo { struct opIndexResult { Foo* that; auto opDispatch(string member, T)(T t) { } } auto opIndex(T)(T t) { return opIndexResult(&this); } } void main() { Foo foo; foo[1337].isnull = true; } ``` dont underestimate what's already possible !
Jun 15
On Saturday, 15 June 2024 at 08:33:07 UTC, Basile B. wrote:On Saturday, 15 June 2024 at 04:58:58 UTC, monkyyy wrote:```d struct Foo { struct opIndexResult(bool isRef, Arg) { Foo* that; static if (isRef) { Arg* _arg; ref Arg arg() => *_arg; } else { Arg _arg; ref Arg arg() return => _arg; } auto ref opDispatch(string member, Rhs)(Rhs rhs) { import std.stdio; writeln("Called <something>[", arg, "].", member, " = ", rhs); } } auto ref opIndex(T)(auto ref T t) { alias Result = opIndexResult!(__traits(isRef, t), T); static if (__traits(isRef, t)) { return Result(&this, &t); } else { import core.lifetime : move; return Result(&this, move(t)); } } } void main() safe { Foo foo; foo[1337].isnull = true; } ``````d mystruct foo; foo[1337].isnull=true; ``` => `foo.opIndexOpAssignOpDispatch!"isnull"(1337,true)` it fits the naming scheme!You can implement an opIndex overload that returns a struct that itself supports opDispatch. ```d struct Foo { struct opIndexResult { Foo* that; auto opDispatch(string member, T)(T t) { } } auto opIndex(T)(T t) { return opIndexResult(&this); } } void main() { Foo foo; foo[1337].isnull = true; } ``` dont underestimate what's already possible !
Jun 17
On Monday, 17 June 2024 at 13:40:13 UTC, Quirin Schroll wrote:On Saturday, 15 June 2024 at 08:33:07 UTC, Basile B. wrote:Nice. While the pattern was clear enough to be developped I'm still slightly concerned about escaping `this`. Probably the result should be set non-copiable with ` disable this(this)`.On Saturday, 15 June 2024 at 04:58:58 UTC, monkyyy wrote:```d struct Foo { struct opIndexResult(bool isRef, Arg) { Foo* that; static if (isRef) { Arg* _arg; ref Arg arg() => *_arg; } else { Arg _arg; ref Arg arg() return => _arg; } auto ref opDispatch(string member, Rhs)(Rhs rhs) { import std.stdio; writeln("Called <something>[", arg, "].", member, " = ", rhs); } } auto ref opIndex(T)(auto ref T t) { alias Result = opIndexResult!(__traits(isRef, t), T); static if (__traits(isRef, t)) { return Result(&this, &t); } else { import core.lifetime : move; return Result(&this, move(t)); } } } void main() safe { Foo foo; foo[1337].isnull = true; } ``````d mystruct foo; foo[1337].isnull=true; ``` => `foo.opIndexOpAssignOpDispatch!"isnull"(1337,true)` it fits the naming scheme!You can implement an opIndex overload that returns a struct that itself supports opDispatch. ```d struct Foo { struct opIndexResult { Foo* that; auto opDispatch(string member, T)(T t) { } } auto opIndex(T)(T t) { return opIndexResult(&this); } } void main() { Foo foo; foo[1337].isnull = true; } ``` dont underestimate what's already possible !
Jun 18
On Tuesday, 18 June 2024 at 09:37:46 UTC, Basile B. wrote:On Monday, 17 June 2024 at 13:40:13 UTC, Quirin Schroll wrote:Copies are largely irrelevant. With `-dip1000`, the escaping `Foo` is diagnosed. Improved code: ```d struct Foo { int x; private static struct OpIndexResult(bool[] isRef, Is...) if (isRef.length == Is.length) { import std.meta; Foo* that; static foreach (i; 0 .. Is.length) static if (isRef[i]) { mixin("Is[i]* _index_", i,";"); mixin(" property ref Is[i] index_", i,"() => *_index_",i,";"); } else { mixin("Is[i] _index_", i,";"); mixin(" property ref Is[i] index_", i,"() => _index_",i,";"); } template indices() { alias indices = AliasSeq!(); static foreach (i; 0 .. Is.length) indices = AliasSeq!(indices, mixin("index_", i)); } auto ref opDispatch(string member, Rhs...)(auto ref Rhs rhs) { import std.stdio; import std.typecons : tuple; writefln("Called Foo(%s)[%(%s%|, %)](%(%s%|, %))", that.x, tuple(indices!()), tuple(rhs)); } } auto opIndex(Is...)(auto ref Is indices) return { import core.lifetime : move; enum bool[] isRef = { bool[] result = new bool[](Is.length); static foreach (i; 0 .. Is.length) result[i] = __traits(isRef, indices[i]); return result; }(); alias Result = OpIndexResult!(isRef, Is); return mixin({ string result = "Result(&this"; static foreach (i, alias index; indices) { static if (__traits(isRef, index)) result ~= mixin(`", &indices[`, i, `]"`); else result ~= mixin(`", move(indices[`, i, `])"`); } return result ~ ")"; }()); } } typeof(Foo()[0,0]) global; void main() safe { Foo foo = Foo(1); auto r = foo[1337, 42]; r.isnull(true, false); // Weird, but okay global = foo[1337, 42]; // Error because `foo` escapes } ```On Saturday, 15 June 2024 at 08:33:07 UTC, Basile B. wrote:Nice. While the pattern was clear enough to be developped I'm still slightly concerned about escaping `this`. Probably the result should be set non-copiable with ` disable this(this)`.On Saturday, 15 June 2024 at 04:58:58 UTC, monkyyy wrote:```d struct Foo { struct opIndexResult(bool isRef, Arg) { Foo* that; static if (isRef) { Arg* _arg; ref Arg arg() => *_arg; } else { Arg _arg; ref Arg arg() return => _arg; } auto ref opDispatch(string member, Rhs)(Rhs rhs) { import std.stdio; writeln("Called <something>[", arg, "].", member, " = ", rhs); } } auto ref opIndex(T)(auto ref T t) { alias Result = opIndexResult!(__traits(isRef, t), T); static if (__traits(isRef, t)) { return Result(&this, &t); } else { import core.lifetime : move; return Result(&this, move(t)); } } } void main() safe { Foo foo; foo[1337].isnull = true; } ``````d mystruct foo; foo[1337].isnull=true; ``` => `foo.opIndexOpAssignOpDispatch!"isnull"(1337,true)` it fits the naming scheme!You can implement an opIndex overload that returns a struct that itself supports opDispatch. ```d struct Foo { struct opIndexResult { Foo* that; auto opDispatch(string member, T)(T t) { } } auto opIndex(T)(T t) { return opIndexResult(&this); } } void main() { Foo foo; foo[1337].isnull = true; } ``` dont underestimate what's already possible !
Jun 20
On Saturday, 15 June 2024 at 04:58:58 UTC, monkyyy wrote:```d mystruct foo; foo[1337].isnull=true; ``` => `foo.opIndexOpAssignOpDispatch!"isnull"(1337,true)` it fits the naming scheme!At this point, D would be getting close to a term language like [Maude](https://en.wikipedia.org/wiki/Maude_system) or [XL](https://xlr.sourceforge.io/#extending-the-syntax).
Jun 20