Compile Time Fun Time
Nicholas Wilson
iamthewilsonator at hotmail.com
Mon Feb 25 07:03:21 UTC 2019
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;
}
More information about the Digitalmars-d-learn
mailing list