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

H. S. Teoh hsteoh at qfbox.info
Thu Jan 5 23:18:11 UTC 2023


On Thu, Jan 05, 2023 at 10:46:07PM +0000, thebluepandabear via Digitalmars-d-learn wrote:
> On Thursday, 5 January 2023 at 17:36:55 UTC, H. S. Teoh wrote:
[...]
> > ```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);
> > }
> > ```
[...]
> Your code with the variable capture doesn't seem to work.

Argh, apparently locals inside the loop body are subject to the same
quirky behaviour. >:-(  Here's a workaround that works:

	foreach (BoardSize boardSize; arr) {
	    Button button = new Button();
	    button.text = format("%sx%s", boardSize[0], boardSize[1]);
	    void wowThisIsDumb(BoardSize size) {
		    button.onButtonClick = {
			eventHandler.settingsWindow_onBoardSizeButtonClick(size);
		    };
	    }
	    wowThisIsDumb(boardSize);
	    button.onButtonClick();
	    _boardSizeRow.addChild(button);
	}

A nested function (or perhaps an inline lambda) is needed to force the
allocation of a dynamic context for the capture.

This is an embarrassment. Why hasn't this been fixed yet? :-(


T

-- 
Being able to learn is a great learning; being able to unlearn is a greater learning.


More information about the Digitalmars-d-learn mailing list