Can we fix this?
deadalnix
deadalnix at gmail.com
Thu Sep 30 00:59:26 UTC 2021
On Wednesday, 29 September 2021 at 16:47:23 UTC, Steven
Schveighoffer wrote:
> What we need is a syntax to specify which values are captured
> and which variables are referenced.
>
> What I normally do if I need something like this is:
>
> ```d
> foreach(int i; [1, 2, 3]) {
> dgList ~= (b) { return {writeln(b);};} (i + 2);
> // or less error prone:
> dgList ~= (i) { return {writeln(i + 2);};} (i);
> }
>
This is where things go off rails. We don't need any new syntax.
We need to stop adding a new gizmo every time something is not
doing the right thing. The ed result is that the original thing
still don't do the right thing and the gizmo also doesn't do the
right thing because it has been though to solve a specific edge
case.
Now, foreach is a high level construct, and just get the same
semantic as what it lowers into. Let's use while loops.
```d
int i = 1;
while (i < 4) {
dgList ~= { writeln(i + 2); }; // still outputs 5 5 5
}
```
Now, this is expected isn't it? There is one and only one i
variable. But let's change things a bit.
```d
int i = 1;
while (i < 4) {
int n = i + 2;
dgList ~= { writeln(n); }; // still outputs 5 5 5
}
```
Now this is wrong. A new n variable is created at each loop
iteration, this isn't the same n. It's easy to convince oneself
that this is the case: n can be made immutable and the code still
compiles, which is evidence that the semantic is that each loop
iteration has a new n variable.
So either we create a new closure for each loop iteration (if a
variable locale to the loop is captured), or making n immutable
must be rejected, because either n in one variable across all
iterations, and it is mutated, or it is not, but it can't be both.
For completeness, it must be noted that the former tends to b
what's expected, this is what C# is doing for instance.
More information about the Digitalmars-d
mailing list