框回调函数在Rascal中返回相同的字符串

时间:2019-01-20 15:37:50

标签: rascal

我试图在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;})
]));

1 个答案:

答案 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()会按预期打印123

在我的示例中,我将其保留为练习的方式,但是当您提出要求时,我准备提供解决方案。祝你好运!