Delegates and values captured inside loops

atzensepp webwicht at web.de
Sun Jan 21 22:44:45 UTC 2024


On Sunday, 21 January 2024 at 20:13:38 UTC, An Pham wrote:
> On Saturday, 20 January 2024 at 15:59:59 UTC, Anonymouse wrote:
>> I remember reading this was an issue and now I ran into it 
>> myself.
>>
>> ```d
>> import std.stdio;
>>
>> void main()
>> {
>>     auto names = [ "foo", "bar", "baz" ];
>>     void delegate()[] dgs;
>>
>>     foreach (name; names)
>>     {
>>         dgs ~= () => writeln(name);
>>     }
>>
>>     foreach (dg; dgs)
>>     {
>>         dg();
>>     }
>> }
>> ```
>>
>> Expected output: `foo`, `bar`, `baz`
>> Actual output:   `baz`, `baz`, `baz`
>>
>> If I make `names` an `AliasSeq` it works, but I need it to be 
>> a runtime array.
>>
>> Is there a workaround?
>
> It is broken by design and the upper afraid to fix it because 
> of broken backward compatible.
> This symptom was same as early C# and MS acknowledge it and 
> fixed it
> Happy coding

Very weird scoping.

The functional programmer's nightmare:
```d
import std.stdio;

     void main()
     {
         auto names = [ "foo", "bar", "baz" ];
         void delegate(int)[] dgs;

         string myname="Original ";

         foreach (name; names)
         {
            int j=0;
            void delegate(int) lambdaFunction =
             (int i)
             {
                 writeln("N:",name," ",myname, j++," ",i); // ok
             };
            j=100;

            dgs ~= lambdaFunction;
         }


         int i=0;
         foreach (dg; dgs)
         {
             dg(i++);
             myname="Side effect ";
         }
     }

     ```
     ```
     ./a.out
     N:baz Original 100 0
     N:baz Side effect 101 1
     N:baz Side effect 102 2

```

Good: the function is indeed invoked.
Why the output starts with 100 and not 0?
Where "lives" variable j which is declared in the scope of the 
foreach-block?



More information about the Digitalmars-d-learn mailing list