On Saturday, 30 May 2020 at 23:39:31 UTC, mw wrote:
Thank you all for the reply.
I hate to write boilerplate code:
class Point {
private int _x;
public int x() {return _x;}
public Point x(int v) {_x=v; return this;}
...
// ... y, z
}
this is what I've got:
$ cat b.d
--------------------------------------------------------------------------------
// dmd -unittest -vcg-ast -c b.d
import std.format;
enum RW(string T, string name) =
format(q{
private %1$s _%2$s;
public %1$s %2$s() {return _%2$s;}
public auto %2$s(%1$s v) {_%2$s = v; return this;}
}, T, name);
class Point {
mixin(RW!("int", "x"));
mixin(RW!("double", "y"));
mixin(RW!("string", "z"));
}
[...]
Is there a better way to achieve this? esp. for the type `int`,
is there any way I don't have to quote it as string?
Thanks.
You can simplify this considerably using a mixin template [1]:
---
mixin template RW(T, string name) {
private T var;
public T get() { return var; }
public typeof(this) set(T val) { var = val; return this; }
mixin("private alias _", name, " = var;");
// two aliases with the same name create an overload set
mixin("public alias ", name, " = get;");
mixin("public alias ", name, " = set;");
}
class Point {
mixin RW!(int, "x");
mixin RW!(int, "y");
// etc.
}
---
You still need string mixins to make the names work, but the rest
can be done without them. Large string mixins tend to be
error-prone and difficult to debug, so it's usually a good idea
to make them as small as you reasonably can [2].
[1] https://dlang.org/spec/template-mixin.html
[2] http://www.arsdnet.net/this-week-in-d/2016-feb-21.html