Re: Delegates and values captured inside loops

2024-01-21 Thread An Pham via Digitalmars-d-learn

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`





For c# reference when they fixed it: 
https://stackoverflow.com/questions/3168375/using-the-iterator-variable-of-foreach-loop-in-a-lambda-expression-why-fails


To have a way out for old behavior by capture reference,
from:  dgs ~= () => writeln(name);
to:  dgs ~= () => writeln(&name);


Re: Delegates and values captured inside loops

2024-01-21 Thread atzensepp via Digitalmars-d-learn

In Ocaml this would look as:
```d
let names =["foo";"bar";"baz"] in
let funmap = List.map (  fun name -> ( fun () -> print_endline 
name)) names in

List.iter ( fun f -> f () ) funmap
;;
~
```
I think in the D-example it is basically one function and not 3.




Re: Delegates and values captured inside loops

2024-01-21 Thread atzensepp via Digitalmars-d-learn

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?




Re: Delegates and values captured inside loops

2024-01-21 Thread An Pham via Digitalmars-d-learn

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




Re: Delegates and values captured inside loops

2024-01-21 Thread Steven Schveighoffer via Digitalmars-d-learn

On Sunday, 21 January 2024 at 14:52:45 UTC, Renato wrote:

On Saturday, 20 January 2024 at 16:53:12 UTC, ryuukk_ wrote:


This is the workaround according to: 
https://issues.dlang.org/show_bug.cgi?id=21929#c9


Go used to have the same issue [but they fixed 
it](https://go.dev/blog/loopvar-preview) so this is no longer a 
problem in Go.


Perhaps D could do something about it for the same reasons the 
Go blog post presented.


Actually, D is much worse. It appears in that post that local 
variables in the loop were scoped on the loop iteration, but just 
not the iteration variables themselves. This means, the machinery 
to properly capture the loop variables was trivial, just change 
the scope where those variables are allocated.


In D, there is no loop scope. So the compiler would have to 
establish a new mechanism to recognize which variables to stick 
into a closure. It's not impossible, but it is not the same scope 
as what Go had to do.


-Steve


Re: Delegates and values captured inside loops

2024-01-21 Thread Anonymouse via Digitalmars-d-learn
On Saturday, 20 January 2024 at 16:32:42 UTC, FeepingCreature 
wrote:


```
foreach (name; names)
{
dgs ~= ((name) => () => writeln(name))(name);
}
```
lol


Thanks, I'll try that.


Re: Delegates and values captured inside loops

2024-01-20 Thread ryuukk_ via Digitalmars-d-learn

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?



```d
import std.stdio;

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


foreach (name; names)
{
(it) {
dgs ~= () => writeln(it);
}(name);
}

foreach (dg; dgs)
{
dg();
}
}
```

This is the workaround according to: 
https://issues.dlang.org/show_bug.cgi?id=21929#c9






Re: Delegates and values captured inside loops

2024-01-20 Thread FeepingCreature via Digitalmars-d-learn

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?


```
foreach (name; names)
{
dgs ~= ((name) => () => writeln(name))(name);
}
```
lol


Re: Delegates and values captured inside loops

2024-01-20 Thread monkyyy via Digitalmars-d-learn

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?


Everything is sucks, if your throwing out compile time functions 
rewriting it as a struct (or generating a struct) is probaly you 
best bet


```d
struct dg{
  string s;
  void opApply(){
s.writeln;
  }
}
```