Thread overview
Is there a plan to add support for closures in CTFE?
Aug 13, 2022
Andrey Zherikov
Aug 13, 2022
Salih Dincer
Aug 13, 2022
Salih Dincer
Aug 16, 2022
Stefan Koch
August 13, 2022

I want to do string processing pipeline is a way that one delegate calls another one and so on. This works perfectly except the case when I want to get a result at compile time.
So I wonder is there a plan to add support for closures at compile time in foreseeable future?

Here is a simple example:

string delegate(string) f1()
{
    return str => "f1 " ~ str;
}

string delegate(string) f2(string delegate(string) dg)
{
    return str => dg("f2 " ~ str);
}

string f3(string delegate(string) dg, string str)
{
    return dg("f3 " ~ str);
}

void main()
{
    import std.stdio;
    writeln(f1.f2.f3("text"));    // works perfectly

    enum s = f1.f2.f3("text");    // Error: closures are not yet supported in CTFE
}

Note: I'm not asking for workarounds (I know how to do that), I'm asking about the plan to fix this.

August 13, 2022

On Saturday, 13 August 2022 at 01:55:28 UTC, Andrey Zherikov wrote:

>

[..] I wonder is there a plan to add support for closures at compile time in foreseeable future?

The problem is on f2...

That works:


    enum s = f1.f3("text");

SDB@79

August 13, 2022

On Saturday, 13 August 2022 at 06:30:13 UTC, Salih Dincer wrote:

>

That works:


    enum s = f1.f3("text");

Sorry for my quick reply. When I tried it with my own codes, I understood what you meant better; during compile time you want to take a delegate and give the delegate...

enum {
   f1 = "1: ", f2 = "2, ", f3 = "3, "
}
alias dstr = string delegate(string);

      auto fun1(dstr dg, string start)
      {
        return dg(f1 ~ start);
      }
      dstr fun2(dstr dg)
      {
        return str => dg(f2 ~ str);
      }
      dstr fun3()
      {
        return str => f3 ~ str;
      }

auto funS(string s) { return f2 ~ s; }
enum s = fun3.fun1("Start").funS;

void main()
{
    import std.stdio;
    s.writeln(": ", typeid(s));

    fun3.fun2.fun1("Start").writeln;
    writeln(fun1(fun2(fun3()), "Start"));
}
/* Prints:
2, 3, 1: Start: immutable(char)[]
3, 2, 1: Start
3, 2, 1: Start
*/

SDB@79

August 16, 2022

On Saturday, 13 August 2022 at 01:55:28 UTC, Andrey Zherikov wrote:

>

I want to do string processing pipeline is a way that one delegate calls another one and so on. This works perfectly except the case when I want to get a result at compile time.
So I wonder is there a plan to add support for closures at compile time in foreseeable future?
[ ... ]

Note: I'm not asking for workarounds (I know how to do that), I'm asking about the plan to fix this.

I am not clued in the official position on this, but I can tell you that it is not a trivial fix.
Due to the design of the interpreter at the moment.
That said it is also not impossible to do. What one would have to do is to allocate a pointer on the ctfe-entry and fill it with a closure chain once a closure is created.
when you then encounter the a usage of a closure variable you look up the frame in the closure chain and use the values from there.

It might be that I am missing something but that should be the basic flow of action.
I remember looking at that issue years ago but at the time I lacked the experience to fix it, and I was also focusing on the newCTFE interpreter.

Cheers,
Stefan