我试图在Rascal中绘制一些框,并尝试为每个框提供自己的回调函数。用鼠标进入该框时,相应的字符串应显示在文本元素中(因此,将box1悬停应显示box1等)。
但是,此刻确实弹出了文本,但仅对3个框显示了“ box3”。
有什么想法吗?
strings = ["box1", "box2", "box3"];
boxes = [ box(
size(100, 100),
onMouseEnter(void() {
output = s;
})
) | s <- strings];
render(hcat([
vcat(boxes),
text(str () {return output;})
]));
答案 0 :(得分:2)
好问题,经典问题。问题的本质是Rascal使用“非捕获闭包”:这意味着从另一个函数返回的函数共享相同的上下文。在您的情况下,这是s
引入的变量s <- strings
。当您在循环中创建函数值时(如此处所述),几乎总是会发生这种情况。解决方案是在返回的函数周围包裹另一个函数层。
这是一个简单的例子:
list[int()] makeClosures()
= [ int() {return i;} | i <- [0,1,2]];
void wrong(){
lst = makeClosures();
println(lst[0]());
println(lst[1]());
println(lst[2]());
}
会令人惊讶地显示值2,
2 and
2`。如前所述,解决方案是引入另一个功能级别:
int() makeClosure(int i)
= int() { return i;};
list[int()] makeClosuresOK()
= [ makeClosure(i) | i <- [0,1,2]];
void right(){
lst = makeClosuresOK();
println(lst[0]());
println(lst[1]());
println(lst[2]());
}
现在呼叫right()
会按预期打印1
,2
和3
。
在我的示例中,我将其保留为练习的方式,但是当您提出要求时,我准备提供解决方案。祝你好运!