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.

Reply via email to