在下面的代码中,我创建3个包含文本1到3的框,在第四个框中我想显示我的鼠标悬停在框上的文本。所以我为每个框设置了一个onMouseEnter FProperty,我更改了第四个框的字符串并告诉它重绘。
bool redraw = false;
str s = "0";
Figure getTextbox() {
return computeFigure(bool() {bool temp = redraw; redraw = false; return temp; },
Figure() {
return text(str() {return s; });
});
}
list[Figure] boxes = [];
for (i <- [1..4]) {
boxes += box(text(toString(i)), onMouseEnter(void () {s = toString(i); redraw = true; }));
}
Figure changer = box(getTextbox());
render(vcat(boxes + changer));
但是,由于某些奇怪的原因,所有三个框都会告诉onMouseEnter方法将第四个框的文本更改为&#34; 3&#34; (最后一个框的值)而不是它们各自的值。
有什么线索的原因?谢谢!
答案 0 :(得分:0)
啊,是的,这是for循环的变量捕获闭包问题,也可以从具有Javascript之类特殊功能的其他语言中获知。这是带有问题的代码:
i
变量onMouseEnter
由void闭包绑定,而不是其值。因此,每次创建并传递给i
的函数时,它都会读取3
变量的最新值。由于在循环终止后调用回调,因此对鼠标输入函数的所有调用都将具有值for (i <- [1..4]) {
newS = toString(i);
boxes += box(text(toString(i)), onMouseEnter(void () {s = newS; redraw = true; }));
}
。
为了解决这个问题并且做了你想做的事情,我相信下面的代码会起作用:
newS
这是有效的,因为对于for循环的每次传递都会创建一个绑定newS
变量的新环境。因此,您将为每个循环获得一个新的i
,而不是重用modified_at
。