On Monday, 25 February 2019 at 08:24:06 UTC, Yevano wrote:
One thing. The variables were reversed. Fixed by changing these lines.

auto result = new Abstraction(vars[$ - 1], f(vars));

foreach_reverse(e; vars[0..$ - 1]) {
    result = new Abstraction(e, result);
}

Yup. I assumed that didn't matter, but was apparently wrong.

One other thing - the static foreach should read 1.. instead of 0.., since it should fail on nilary lambdas. You could also argue it should give better error messages when you do things like L!((int n) => n), pass variadic templated functions to it, or just plain give it something other than a lambda.

It might also benefit from checking __traits(compiles, f(Repeat!(i, Variable.init))), as typeof(null) is valid but might not behave the way you expect a Variable to do.

Here's a version with these issues amended:

Abstraction L(alias f)() {
    import std.meta : Repeat;
    enum maxArgs = 20;
    static foreach (i; 1..maxArgs) {
static if (__traits(compiles, f(Repeat!(i, Variable.init)))) {
            // Check if there has already been a match
            static if (__traits(compiles, { vars[0] = null; })) {
                static assert(false, "Multiple matches in L.");
            }
            Repeat!(i, Variable) vars;
            // Initialize vars in opposite order
            foreach_reverse (ref e; vars) {
                e = new Variable();
            }
            auto result = new Abstraction(vars[0], f(vars));
            foreach (e; vars[1..$]) {
                result = new Abstraction(e, result);
            }
            return result;
        }
    }
    // Check if there have been any matches
    static if (!__traits(compiles, { vars[0] = null; })) {
        static assert(false, "No matches in L.");
    }
}

--
  Simen

Reply via email to