Can we fix this?

Steven Schveighoffer schveiguy at gmail.com
Wed Sep 29 16:47:23 UTC 2021


On 9/29/21 10:16 AM, jfondren wrote:
> On Wednesday, 29 September 2021 at 10:44:53 UTC, Imperatorn wrote:
>> https://issues.dlang.org/show_bug.cgi?id=2043
>>
>> Impossible?
> 
> ... Documentation:
> 
> D has two kinds of blocks, the `{ ... }` kind and the `(){ ... }();` 
> kind. Within the former, for efficiency, [something about this bug]. 
> Within the latter, closure environments will be as expected from other 
> languages at the cost of additional allocation. These "bubble blocks" 
> are admittedly ugly but this is part of D's firm stand against the 
> programming practices of the Scheme community.
> 
> ```d
> void delegate()[] dgList;
> 
> void main() {
>      import std.stdio : writeln;
> 
>      foreach(int i; [1, 2, 3]) {
>          auto b = i+2;
>          dgList ~= { writeln(b); };
>          writeln(&b); // b will be the *same* on each iteration
>      }
>      foreach (dg; dgList)
>          dg(); // output: 5 5 5
> }
> ```
> 
> vs.
> 
> ```d
> void delegate()[] dgList;
> 
> void main() {
>      import std.stdio : writeln;
> 
>      foreach(int i; [1, 2, 3]) (){
>          auto b = i+2;
>          dgList ~= { writeln(b); };
>          writeln(&b); // b will be *unique* on each iteration
>      }();
>      foreach (dg; dgList)
>          dg(); // output: 3 4 5
> }
> ```

This is not what I would have ever thought of, and it's kind of prone to 
error, since `i` is still used from within the lambda. It would not be 
hard to mess it up:

```d
foreach(int i; [1, 2, 3]) (){
     dgList ~= { writeln(i + 2); }; // still outputs 5 5 5
}();
```

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);
}

```

Which specifies the captured variable. But it's a lot of punctuation.

Some imagined syntax?

```d
dgList ~= (@capture i) {writeln(i + 2);};
// or:
dgList ~= (@capture i) => writeln(i + 2);
```

-Steve


More information about the Digitalmars-d mailing list