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

box callback functions returning the same string in Rascal

我正在尝试在 Rascal 中绘制一些方框并尝试为每个方框提供其自己的回调函数。在用鼠标输入框时,相应的字符串应该显示在文本元素中(因此悬停 box1 应该显示 box1 等)。

但是,目前确实会弹出文本,但只显示 "box3" 3 个框的每个框。

有什么想法吗?

strings = ["box1", "box2", "box3"];

boxes = [ box(
    size(100, 100),
    onMouseEnter(void() {
        output = s;
    })
) | s <- strings];

render(hcat([
    vcat(boxes),
    text(str () {return output;})
]));

好问题,经典问题。问题的本质是 Rascal 使用 "non-capturing closures":这意味着从另一个函数返回的函数共享相同的上下文。在您的例子中,这是由 s <- strings 引入的变量 s。当您在循环中创建函数值时(就像您在此处所做的那样),这几乎总是会发生。解决方案是在返回的函数周围再包裹一个函数层。

这是一个简单的例子:

list[int()] makeClosures()
    =  [ int() {return i;} | i <- [0,1,2]];

void wrong(){
    lst = makeClosures();
    println(lst[0]());
    println(lst[1]());
    println(lst[2]());
}

这将令人惊讶地打印值 2,2and2`。解决方案如前所述,引入另一个功能级别:

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

我将它作为练习留作练习,在您的示例中如何完成此操作,但我准备在您提出要求时提供解决方案。祝你好运!