How to avoid variable capturing in `foreach` loop with lambdas?

thebluepandabear therealbluepandabear at protonmail.com
Thu Jan 5 22:46:07 UTC 2023


On Thursday, 5 January 2023 at 17:36:55 UTC, H. S. Teoh wrote:
> On Thu, Jan 05, 2023 at 11:55:33AM +0000, thebluepandabear via 
> Digitalmars-d-learn wrote: [...]
>> ```D
>> foreach (BoardSize boardSize; arr) {
>>     Button button = new Button();
>>     button.text = format("%sx%s", boardSize[0], boardSize[1]);
>>     button.onButtonClick = {
>> eventHandler.settingsWindow_onBoardSizeButtonClick(boardSize);
>>     };
>>     button.onButtonClick();
>>     _boardSizeRow.addChild(button);
>> }
>> ```
>
> This is a classic D trap: the loop variable is only allocated 
> once, and the closure captures the single location where the 
> loop variable resides, thus every delegate from every loop 
> iteration will see the same value when they are run later, 
> i.e., the last value of the loop index. Do this instead:
>
> ```D
> foreach (BoardSize boardSize; arr) {
>     Button button = new Button();
>     button.text = format("%sx%s", boardSize[0], boardSize[1]);
>     BoardSize size = boardSize; // force separate capture
>     button.onButtonClick = {
>         
> eventHandler.settingsWindow_onBoardSizeButtonClick(size);
>     };
>     button.onButtonClick();
>     _boardSizeRow.addChild(button);
> }
> ```
>
> This is arguably a language bug (I can't imagine any sane use 
> case where somebody would actually want the current semantics). 
>  But we have not be successful in convincing Walter about 
> this...
>
>
> T

Your code with the variable capture doesn't seem to work.


More information about the Digitalmars-d-learn mailing list