Re: How do I generate `setX` methods for all private mutable variables in a class?
On Monday, 5 June 2023 at 18:54:30 UTC, cc wrote: [...] Is there a way to check for mutability as well? I have both immutable and mutable fields. I would like to generate setters for mutable fields only.
Re: How do I generate `setX` methods for all private mutable variables in a class?
On 6/6/23 09:13, Basile B. wrote: > yeah I know that opDispatch is disliked because it is tried in a SFINAE > fashion, as citicized by Adam. But on the other side it's the best opover. I like how it helped in my current project: user.someShellCommand("-foo", "-bar"); opDispatch makes a command string, passes it to executeShell, takes care of the return code and dumps its output if there was an error. Ali
Re: How do I generate `setX` methods for all private mutable variables in a class?
On Tuesday, 6 June 2023 at 14:23:59 UTC, Steven Schveighoffer wrote: On 6/5/23 11:33 AM, Basile B. wrote: [...] Ugh, don't do it that way. Always give opDispatch a template constraint or it will suck to use. Also, given the problem constraints, you can build the method automatically using the string. ```d auto opDispatch(string member, T)(auto ref T t) if(member.startsWith("set")) { mixin(toLower(m[3]), m[4 .. $], " = t;"); } ``` -Steve yeah I know that opDispatch is disliked because it is tried in a SFINAE fashion, as citicized by Adam. But on the other side it's the best opover.
Re: How do I generate `setX` methods for all private mutable variables in a class?
On 6/5/23 11:33 AM, Basile B. wrote: On Monday, 5 June 2023 at 15:13:43 UTC, Basile B. wrote: On Monday, 5 June 2023 at 13:57:20 UTC, Ki Rill wrote: How do I generate `setX` methods for all private mutable although I did not spent time on the setter body... I suppose the question was more about the metprogramming technic, and that you don't want a pre-mashed solution ;) By the way...an other solution is to use [opDispatch](https://dlang.org/spec/operatoroverloading.html#dispatch): ```d class Color {} class Rectangle { private Color fillColor; private Color strokeColor; private uint strokeWidth; auto opDispatch(string member, T)(auto ref T t) { static if (member == "setStrokeWidth") {} else static if (member == "setStrokeColor") {} else static if (member == "setFillColor") {} else static assert(0, "cannot set " ~ member); return this; } } void main() { (new Rectangle) .setStrokeWidth(0) .setStrokeColor(null) .setFillColor(null); } ``` Ugh, don't do it that way. Always give opDispatch a template constraint or it will suck to use. Also, given the problem constraints, you can build the method automatically using the string. ```d auto opDispatch(string member, T)(auto ref T t) if(member.startsWith("set")) { mixin(toLower(m[3]), m[4 .. $], " = t;"); } ``` -Steve
Re: How do I generate `setX` methods for all private mutable variables in a class?
On Monday, 5 June 2023 at 15:28:34 UTC, Paul Backus wrote: Is there a reason you can't just make these fields `public`? My bet is that OP actually wants to generate something like ```d void setStrokeWidth(uint value) { if (value = strokeWidth) return; strokeWidth = value; redraw(); // or maybe... // needRedraw = true; } ``` that's a common pattern in 2D graphic libraries.
Re: How do I generate `setX` methods for all private mutable variables in a class?
On Monday, 5 June 2023 at 15:28:34 UTC, Paul Backus wrote: Is there a reason you can't just make these fields `public`? My bet is that OP actually wants to generate something like ```d void setStrokeWidth(uint value) { if (value = strokeWidth) return; strokeWidth = value; redraw(); // or maybe... // needRedraw = true; } ``` that's a common pattern in 2D graphics libraries
Re: How do I generate `setX` methods for all private mutable variables in a class?
On Monday, 5 June 2023 at 18:54:30 UTC, cc wrote: On Monday, 5 June 2023 at 13:57:20 UTC, Ki Rill wrote: How do I generate `setX` methods for all private mutable variables in my class? Do I need to use `__traits`? ```d mixin template GenerateSetters() { static foreach (idx, field; typeof(this).tupleof) static if (__traits(getVisibility,field) == "private") { mixin(q{ void %SETTER(typeof(this.tupleof[idx]) _) { %NAME = _; } } .replace("%NAME", field.stringof) .replace("%SETTER", "set"~toUpper(field.stringof[0..1]) ~ field.stringof[1..$]) ); } } class Rectangle { private Color fillColor; private Color strokeColor; private uint strokeWidth; this(int x, int y) {} mixin GenerateSetters; } void main() { auto rect = new Rectangle(0, 0); rect.setStrokeWidth(4); assert(rect.strokeWidth == 4); } ``` Thank you! That is exactly what I needed. Although another solution provided by Basile B. using attributes opens a door for other posibilities... I don't usually use metaprogramming or code generation much, this is an eye-opening experience.
Re: How do I generate `setX` methods for all private mutable variables in a class?
On Monday, 5 June 2023 at 13:57:20 UTC, Ki Rill wrote: How do I generate `setX` methods for all private mutable variables in my class? Do I need to use `__traits`? ```d mixin template GenerateSetters() { static foreach (idx, field; typeof(this).tupleof) static if (__traits(getVisibility,field) == "private") { mixin(q{ void %SETTER(typeof(this.tupleof[idx]) _) { %NAME = _; } } .replace("%NAME", field.stringof) .replace("%SETTER", "set"~toUpper(field.stringof[0..1]) ~ field.stringof[1..$]) ); } } class Rectangle { private Color fillColor; private Color strokeColor; private uint strokeWidth; this(int x, int y) {} mixin GenerateSetters; } void main() { auto rect = new Rectangle(0, 0); rect.setStrokeWidth(4); assert(rect.strokeWidth == 4); } ```
Re: How do I generate `setX` methods for all private mutable variables in a class?
On Monday, 5 June 2023 at 15:13:43 UTC, Basile B. wrote: On Monday, 5 June 2023 at 13:57:20 UTC, Ki Rill wrote: How do I generate `setX` methods for all private mutable although I did not spent time on the setter body... I suppose the question was more about the metprogramming technic, and that you don't want a pre-mashed solution ;) By the way...an other solution is to use [opDispatch](https://dlang.org/spec/operatoroverloading.html#dispatch): ```d class Color {} class Rectangle { private Color fillColor; private Color strokeColor; private uint strokeWidth; auto opDispatch(string member, T)(auto ref T t) { static if (member == "setStrokeWidth") {} else static if (member == "setStrokeColor") {} else static if (member == "setFillColor") {} else static assert(0, "cannot set " ~ member); return this; } } void main() { (new Rectangle) .setStrokeWidth(0) .setStrokeColor(null) .setFillColor(null); } ``` Sure the first solution takes advantage of D features but to generate code that finally looks like C# or Delphi (`Set`, `Get`; `property`, etc.) On top of that I tend to prefer the later solution because self-introspection based on `__traits` has corner issues, especially when typecons-like structures are used for the members (e.g sumtype, nullable, etc.).
Re: How do I generate `setX` methods for all private mutable variables in a class?
On Monday, 5 June 2023 at 13:57:20 UTC, Ki Rill wrote: How do I generate `setX` methods for all private mutable variables in my class? Do I need to use `__traits`? I need this for my [tiny-svg](https://github.com/rillki/tiny-svg) project to generate `setX` methods for all Shapes. Example: ```D class Rectangle { private immutable ...; private Color fillColor; private Color strokeColor; private uint strokeWidth; this(int x, int y) {...} mixin(???); // I need this: Rectangle setFillColor(Color color) {...} Rectangle setStrokeColor(Color color) {...} Rectangle setStrokeWidth(uint color) {...} } ``` Is there a reason you can't just make these fields `public`? D supports property accessors, so you can always go back and make them `private` later on if it turns out you need to. For example: ```d // Before class MyClass1 { public int data; } void example1(MyClass1 c) { c.data = 123; // set int n = c.data; // get } // After class MyClass2 { private int data_; int data() { return data; } void data(int value) { data = value; } } void example2(MyClass2 c) { // Usage is exactly the same c.data = 123; // set int n = c.data; // get } ```
Re: How do I generate `setX` methods for all private mutable variables in a class?
On Monday, 5 June 2023 at 13:57:20 UTC, Ki Rill wrote: How do I generate `setX` methods for all private mutable variables in my class? Do I need to use `__traits`? I need this for my [tiny-svg](https://github.com/rillki/tiny-svg) project to generate `setX` methods for all Shapes. Example: ```D class Rectangle { private immutable ...; private Color fillColor; private Color strokeColor; private uint strokeWidth; this(int x, int y) {...} mixin(???); // I need this: Rectangle setFillColor(Color color) {...} Rectangle setStrokeColor(Color color) {...} Rectangle setStrokeWidth(uint color) {...} } ``` Usage: ```D new Rectangle(10, 10) .setFillColor(Colors.white) .setStrokeColor(Colors.black) .setStrokeWidth(3); ``` You need to put an user attribute on the fieldd then to use static introspection to generate the setters. Very basically that works like that ```d enum Set; class Color {} auto generateSetters(T)() { string result; import std.traits; static foreach (m; __traits(allMembers, T)) {{ alias member = __traits(getMember, T, m); static if (hasUDA!(member, Set)) result ~= "void set" ~ m ~ "(" ~ typeof(member).stringof ~ "){}\n"; }} return result; } class Rectangle { @Set private Color fillColor; @Set private Color strokeColor; @Set private uint strokeWidth; mixin(generateSetters!(Rectangle)()); } void main() { with (new Rectangle) { setstrokeWidth(0); setstrokeColor(null); setfillColor(null); } } ``` although I did not spent time on the setter body... I suppose the question was more about the metprogramming technic, and that you don't want a pre-mashed solution ;)
How do I generate `setX` methods for all private mutable variables in a class?
How do I generate `setX` methods for all private mutable variables in my class? Do I need to use `__traits`? I need this for my [tiny-svg](https://github.com/rillki/tiny-svg) project to generate `setX` methods for all Shapes. Example: ```D class Rectangle { private immutable ...; private Color fillColor; private Color strokeColor; private uint strokeWidth; this(int x, int y) {...} mixin(???); // I need this: Rectangle setFillColor(Color color) {...} Rectangle setStrokeColor(Color color) {...} Rectangle setStrokeWidth(uint color) {...} } ``` Usage: ```D new Rectangle(10, 10) .setFillColor(Colors.white) .setStrokeColor(Colors.black) .setStrokeWidth(3); ```