On Sunday, 27 September 2020 at 10:17:39 UTC, realhet wrote:
On Saturday, 26 September 2020 at 17:13:17 UTC, Anonymouse
wrote:
On Saturday, 26 September 2020 at 16:05:58 UTC, realhet wrote:
The closest I can get is @(S.init.c(9).f(42)) with use of
opDispatch, which is easier to read but still ugly.
All I can get is that the
- an identifier of a member is stronger than the opDispatch. ->
Error: function expected before (), not S(0, 0).c of type int
- and if I prefix it with '_' it ruins toString. -> Error: no
property toString for type onlineapp.S
import std.stdio, std.range, std.algorithm, std.traits,
std.meta, std.conv, std.string, std.uni, std.meta,
std.functional, std.exception;
struct S{
int a, b;
auto opDispatch(string name, T)(T value)
if(name.startsWith("_"))
{
mixin(name[1..$], "= value;");
return this;
}
}
void main(){
S.init._a(5).writeln;
}
Now I'm more confused, as the compiler completely ignores the
if(name.startsWith("_")) constraint o.O
It works if you specialise opDispatch to take an int parameter
instead of a type T. It smells like a bug but I don't know enough
to say.
I used two opDispatches to be able to avoid having to use _a and
_b, and std.algorithm.comparison.among to constrain them.
struct S{
private int _a, _b;
auto opDispatch(string name)(int value)
if (name.among("a", "b"))
{
mixin("_", name, "= value;");
return this;
}
auto opDispatch(string name)()
if (name.among("a", "b"))
{
mixin("return _", name, ";");
}
}
void main(){
S.init.a(123).b(456).writeln;
S().b(456).a(123).writeln; // Alternative syntax, may not
work if opCall is defined
}
It's brittle in that you have to update and sync the two
among("a", "b") constraints every time you add or remove a field,
but I can't seem to get the names by introspection without it
endlessly recursing over opDispatch again.