2016-12-09 4 views
2

다음 코드에서 1에서 3까지의 텍스트로 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)); 

그러나, 어떤 이상한 이유로 모두 세 개의 상자 대신 개별 값의 "3"(마지막 상자의 값)에 네 번째 상자의 텍스트를 변경하려면 onMouseEnter 방법을 알려드립니다.

실마리가 있습니까? 감사!

답변

0

아 그렇습니다. 이것은 자바 스크립트와 같은 특정 기능이있는 다른 언어에서도 알려진 for 루프의 클로저 캡처 문제를 나타내는 변수입니다.

for (i <- [1..4]) { 
    boxes += box(text(toString(i)), onMouseEnter(void() {s = toString(i); redraw = true; })); 
} 

변수 i가 무효 폐쇄에 구속되어 있지 값 :이 문제에 코드입니다. 따라서 생성되어 onMouseEnter에 전달 된 함수는 매번 i 변수의 최신 값을 읽습니다. 루프가 종료 된 후에 콜백이 호출되기 때문에 마우스 입력 함수에 대한 모든 호출의 값은 3이됩니다.

다음 코드는 내가 생각 일 것 "당신이 원하는 일을"이 문제를 해결하고 :

for (i <- [1..4]) { 
     newS = toString(i); 
     boxes += box(text(toString(i)), onMouseEnter(void() {s = newS; redraw = true; })); 
    } 

이 작동하기 때문에 newS 변수를 결합하는 새로운 환경이 생성됩니다 루프에 대한 모든 패스 . 따라서 재사용 된 루프 대신 모든 루프에 대해 newS을 새로 얻을 수 있습니다. i.