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

Reply via email to