On Sunday, 16 October 2016 at 13:58:51 UTC, Andrei Alexandrescu
wrote:
I was thinking it would be handy if tuples had a way to access
a field by name at runtime. E.g.:
Tuple!(int, "a", double, "b") t;
string x = condition ? "a" : "b";
double v = t.get!string(x, 3.14);
The get method takes the field name and the type of the
presumed field, and it returns the value of the field in the
tuple. If no field by that name and type, return the second
argument.
Rquirements:
* Do not throw - allow the second argument to be a throwing
delegate
* Do not add overhead if the method is never used
* Figure out a reasonable (but not all too complicated) way to
deal with implicit conversions, e.g. if x == "a" in the the
code above, should it return 3.14 or convert the int to double?
* Handle qualifiers appropriately
Andrei
When I need to choose at runtime a value out of multiple choices
with different types(all available at compile-time), and handle
them similarly, I like to use something like this:
import std.stdio;
import std.typecons;
import std.conv;
auto getAnd(alias dlg, T)(T tup, string key) {
final switch (key) foreach (fieldName; T.fieldNames) {
case fieldName:
return dlg(__traits(getMember, tup, fieldName));
}
}
void main() {
Tuple!(int, "a", double, "b") t;
t.a = 3;
t.b = 3.14;
string toString(string key) {
return t.getAnd!(x => x.to!string)(key);
}
assert (toString("a") == "3");
assert (toString("b") == "3.14");
}
The idea is to pass a delegate as an "alias", and instantiate it
multiple times, once for each field. This means that instead of
being forced to convert them to a common type, we can write once
code that uses the correct type for each field.