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