On Monday, 25 February 2019 at 06:51:20 UTC, Yevano wrote:
I am writing a domain specific language of sorts in D for the lambda calculus. One of my requirements is that I should be able to generate expressions like this:

new Abstraction(v1, M)

like this:

L!(x => M)

It is common to want to write things like

L!(x => L!(y => M))

but it is much nicer to write that like

L!((x, y) => M)

So, I have created a templated function for this.

Abstraction L(alias f)() {
    static if(__traits(compiles, f(null))) {
        auto v1 = new Variable;
        return new Abstraction(v1, f(v1));
    } else static if(__traits(compiles, f(null, null))) {
        auto v1 = new Variable;
        auto v2 = new Variable;
return new Abstraction(v1, new Abstraction(v2, f(v1, v2)));
    } else static if(__traits(compiles, f(null, null, null))) {
        auto v1 = new Variable;
        auto v2 = new Variable;
        auto v3 = new Variable;
return new Abstraction(v1, new Abstraction(v2, new Abstraction(v3, f(v1, v2, v3))));
    }
}

This only works for at most 3 parameter delegates. If I want to add more, I have to linearly add more static ifs in the obvious way. However, I believe I can make this function scalable using string mixins and other magic. Any insight into this is much appreciated.

import std.traits;
Abstraction L(alias f)() {
     alias Args = Parameters!f;
     Args v;
     foreach(i; 0 .. v.length) v[i] =  new Variable;
     auto _f = f(v);
     auto abstraction = new Abstraction(v[$-1],_f);
     foreach_reverse(e; v[ 0 .. $-2])
          abstraction =  new Abstraction( e, abstraction);
     return abstraction;
}

Reply via email to