SqueakByExample:3.5
블록 문법(Block syntax)
블록은 표현식의 평가를 연기하는 메커니즘을 제공합니다. 블록은 본질적으로 익명 기능(anonymous function)입니다. 블록은 메시지 값을 블록에 보냄으로써 평가됩니다. 블록은 어떤 값도 답하지 않는 명백한 리턴 (↑과 함께)이 없으면, 그 블록의 바디에 마지막 표현식의 값을 답합니다.
[ 1 + 2 ] value → 3
블록은 각각 맨 앞에 콜론(leading colon)으로 공표되는 파라미터를 취합니다. 수직바는 블록의 바디로부터 파라미터 공표(the parameter declaration)를 분리합니다.
하나의 파라미터를 가진 블록을 평가하려면, 그 파라미터를 반드시 하나의 인수와 함께 메시지 값: (value:)을 보내야 합니다. 두 개의 파라미터 블록은 반드시 값:값으로(value:value) 보내야 하고 이런 방식으로 4개의 인수까지 보낼 수 있습니다.
[ :x | 1 + x ] value: 2 →3
[ :x :y | x + y ] value: 1 value: 2 → 3
만약 여러분이 4개의 파라미터 보다 더 많은 파라미터를 가진 블록을 갖고 있다면, 반드시 vaulewithAugument:를 사용해야 하고 그 인수들을 배열(array)로 패스해야 합니다. (많은 개수의 파라미터를 가진 블록은 종종 디자인 문제의 신호가 됩니다) 블록은 메소드에 있는 로컬 변수 공표(local variable)와 같이, 수직바에 의해 둘러싸인 로컬 변수(local variables)를 공표할 수 있습니다. 로컬 변수는 인수 이후에 공표됩니다.
[ :x :y | | z | z := x+ y. z ] value: 1 value: 2 → 3
블록은 실제로 어휘적 클로저(lexical closures)이며, 그 이유는 주변 환경의 변수들을 참조할 수 있기 때문입니다. 다음 블록은 그 블록과 가까운 환경의 변수 x를 참조합니다:
| x |
x := 1.
[ :y | x + y ] value: 2 → 3
블록은 클래스 BlockContext의 인스턴스 입니다. 이 의미는 블록은 오브젝트이므로, 변수에 할당될 수 있고, 모든 다른 오브젝트와 똑 같이 인수로서 패스될 수 있다는 것입니다.
경고: 스퀵의 현재 버전 (3.9)은 트루 블록 클로저(true block-closure)를 실제 지원하지 않으며, 그 이유는 블록 인수가 englosing 메소드의 임시 변수로서 실제적으로 시뮬레이션 되기(구현 되기) 때문입니다. 풀 블록 클로저(full block closure)를 지원하는 새로운 컴파일러가 있지만, 그 컴파일러는 여전히 작업중이며, 디폴트로 사용되지 않습니다.
어느 정도 모호한 상황에서, 이 문제는 작명 충돌(naming conflict)로 이끌 수 있습니다. 이 상황은 스퀵이 스몰토크의 초기 실행에 기초하였기 때문에 발생합니다. 만약 여러분이 이 문제를 직면하신다면, 메소드 fixTemps의 발신자(senders)를 보시거나 클로저 컴파일러(the closure compiler)를 로드하시기 바랍니다.