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

tsbockman thomas.bockman at gmail.com
Thu Jan 5 13:58:30 UTC 2023


On Thursday, 5 January 2023 at 13:05:46 UTC, thebluepandabear 
wrote:
> Update some time later: the only way (oof!) around this seems 
> to be using a `static foreach` with arrays:
>
> ```D
> Button[3] b;
>
> static foreach (indx, BoardSize boardSize; arr) {
>     b[indx] = new Button();
>     b[indx].text = format("%sx%s", boardSize[0], boardSize[1]);
>     b[indx].onButtonClick = {
>         
> eventHandler.settingsWindow_onBoardSizeButtonClick(boardSize);
>     };
>     _boardSizeRow.addChild(b[indx]);
> }
> ```

This is semantically equivalent to copying and pasting the loop 
body `arr.length` number of times, substituting the expression 
`arr[indx]` for `boardSize`, and the literal value of `indx` for 
`indx`.

Unlike with a runtime (non-`static`) loop, the event handler 
closure does not capture a reference to `boardSize` or `indx`, 
because they don't actually exist at runtime and so cannot be 
referenced. Instead, `arr.length` different event handler 
functions are created at compile time, with each having the 
appropriate `indx` literal substituted.

So, while it does work as long as `arr.length` is known at 
compile time, it will cause a ton of needless code bloat unless 
`arr.length` is very small.

> Any other ways of fixing this annoying issue?

Yes, see [my earlier 
reply](https://forum.dlang.org/post/fwnccjunvnffmtaholqc@forum.dlang.org) for an explanation of how to get your original run time loop working as intended.



More information about the Digitalmars-d-learn mailing list