| |
| Posted by atzensepp in reply to An Pham | PermalinkReply |
|
atzensepp
Posted in reply to An Pham
| 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.
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:
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?
|