Compile Time Fun Time

Simen Kjærås simen.kjaras at gmail.com
Mon Feb 25 12:33:26 UTC 2019


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


More information about the Digitalmars-d-learn mailing list