On Friday, 18 October 2024 at 12:07:24 UTC, Kadir Erdem Demir wrote:
It seems [=] functionality C++ does not exist in D.

No, D does not have this functionality.

By using a helper function I made that example work.

```d

import std.stdio;

auto localFoo(int x) {
    return (){ return x;};
}

void main() {
    int x = 10;

    auto lambda = (int capturedX = x) {
        writeln("Captured reference : ", capturedX);
    };

    auto localFoo = localFoo(x);

    x = 20;
writeln(localFoo());// Outputs: Captured value: 10 --> That is what I need
    lambda();     // Outputs: 20

}

```

D captures all closures via allocation onto the heap. Using `localFoo` is the correct way to do this.

For nested functions, it has a reference to the outer stack frame, this is different.

But your example is even different, a default parameter means "pass this parameter if none is passed". So your call to `lambda()` is treated as if you wrote `lambda(x)`. It's not captured on definition, it's passed on usage.


But when I trying the same technique on std.Thread it does not work. Always reference is being captured.

```d


void InitCurrencies()
    {
        auto captureFuction(int index)
        {
            return (){
                auto localIndex = index;
string[] currentChunk = ChunkedExchangePairNames(localIndex);
                writeln("Thread index: ", localIndex, " pairs:
 ", currentChunk.join(";"));
                foreach (exchangeName; currentChunk)
                    Connect(exchangeName, WebSocketType.All);
                WebSocket.eventLoop(localLoopExited);
            };
        }

        for(int i = 0; i < m_ThreadCount; i++)
        {
            auto work = captureFuction(i);
            auto worker = new Thread({
                work();
            });
            m_workerList ~= worker;
        }

        foreach(worker; m_workerList)
        {
            worker.start();
        }
    }

```     
writeln("Thread index: ", localIndex, " pairs: ", currentChunk.join(";"))
Always prints the last value of my for loop.

In this case, you are passing in a local anonymous function which uses the stack frame pointer to find the value stored at `work`. This value gets changed each time through the loop.

What you need to do is simply pass the work function into the thread:

```d
auto worker = new Thread(work);
```

This copies the lambda *by value* into the Thread, and then you can change work, it won't affect that copy.

Note that it is a very long standing issue that closures are not done based on the full scope of everything -- only the stack frame of the function is used.

-Steve

Reply via email to