www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - nogc and lambdas

reply Manu <turkeyman gmail.com> writes:
I'm finding it extremely inconvenient to write  nogc event-driven code when
I can't use lambdas because they always want to allocate closures when they
shouldn't be.

Can anyone take a look at this issue:
https://issues.dlang.org/show_bug.cgi?id=24838

The problem is this:

class MyClass
{
    void doSomething();

    void myMethod()  nogc
    {
        acceptsCallback(&notLambda);  // this works; delegate is
created from the method
        acceptsCallback((){ doSomething(); }); // doesn't work!
closure needlessly tries to allocate
    }

    void notLambda()
    {
        doSomething();
    }
}


Here we have a method that calls some kind of async that receives a
callback.
Obviously, I can pass a method at a callback as shown in the first line of
myMethod; but the second line, where I pass the same code as a lambda fails.

The problem here is that the language is trying to allocate a closure
around `this` because the lambda calls another method.
This is totally redundant; there's no need to allocate a closure if `this`
is the only thing that's captured... because it should just accept `this`
as the context directly!
This lambda isn't a closure, it's a METHOD.
The compiler needs to determine that `this` is the only capture, and then
abandon the closure and synthesise the lambda as a regular method.

This will make lambda's about 100x more useful in  nogc code. And even if
you don't care about  nogc; it also eliminates a common source of garbage,
and a pointless double-indirection when accessing `this` via another
redundant `this`.

I can't think of any time I've ever written a lambda that I actually *want*
to allocate a closure to access latent local scope data, but I almost
always refer to sibling members of the calling function to implement some
sort of callback response.
Oct 30
parent Sebastiaan Koppe <mail skoppe.eu> writes:
On Wednesday, 30 October 2024 at 15:25:06 UTC, Manu wrote:
 The problem here is that the language is trying to allocate a 
 closure
 around `this` because the lambda calls another method.
 This is totally redundant; there's no need to allocate a 
 closure if `this`
 is the only thing that's captured... because it should just 
 accept `this`
 as the context directly!
 This lambda isn't a closure, it's a METHOD.
 The compiler needs to determine that `this` is the only 
 capture, and then
 abandon the closure and synthesise the lambda as a regular 
 method.
I am starting to dislike closures altogether, and would prefer a way to explicit handle captures. For your use case, perhaps something like: ``` acceptsCallback(()[this=&this]{ doSomething(); }); ```
Oct 30