변수 참조와 #%top
변수 참조와 #%top
Racket에서 식별자(identifier)를 이름으로 쓰면 그 이름에 묶인 값을 가리킵니다. 그런데 어떤 식별자는 아직 어떤 바인딩에도 묶이지 않았을 수 있어요. 이 문서에서는 식별자 참조가 어떻게 처리되는지, 그리고 그 과정에서 등장하는 #%top 폼에 대해 설명할게요.
출처: Racket Reference
본문
3.5 변수 참조와 #%top
id
id는 트랜스포머 바인딩(확장 참고)으로 묶이지 않은 경우, 최상위(top-level), 모듈 수준(module-level), 또는 지역(local) 바인딩을 가리킵니다. 실행 시점(run-time)에 이 참조는 그 바인딩과 연결된 위치에 저장된 값으로 평가됩니다.
익스팬더(expander)가 모듈 수준이나 지역 바인딩으로 묶이지 않은 id를 만나면, 그 표현식을 (#%top . id)로 변환합니다. 이때 #%top에게 id의 어휘적 문맥(lexical context)을 줍니다. 보통 그 문맥은 #%top을 가리키게 되죠. 자세한 내용은 확장 단계를 참고하세요.
예시:
> (define x 10)
> x
10
> (let ([x 5]) x)
5
> ((lambda (x) x) 2)
2
(#%top . id)
id가 모듈 수준이나 최상위 변수로 묶여 있을 때 id와 동등합니다. 최상위 문맥에서 (#%top . id)는 id에 지역 바인딩이 없는 한, id가 묶여 있지 않거나 문법(syntax)으로 묶여 있어도 항상 최상위 변수를 가리킵니다. 모든 문맥에서 (#%top . id)는 id에 지역 바인딩이 있으면 문법 오류입니다.
모듈 폼 안에서 (#%top . id)는 id가 그 모듈 안에 정의되어 있고 그 문맥에 지역 바인딩이 없는 한, 그냥 id로 확장됩니다. 위상(phase) 수준 0에서 (#%top . id)는 id가 묶여 있지 않으면 즉시 문법 오류입니다. 위상 수준 1 이상에서는, id가 모듈 본문 부분 확장이 끝날 때까지 해당 위상에 정의되지 않으면 문법 오류가 보고됩니다.
익스팬더가 #%top 식별자를 어떻게 도입하는지에 대한 정보는 확장 단계를 참고하세요.
예시:
> (define x 12)
> (#%top . x)
12
변경 사항:
- version 6.3 of package base: 최상위 문맥에서
#%top의 도입을 묶여 있지 않은 식별자(unbound identifiers)에만 적용하도록 변경됨. - version 8.2.0.7: 지역 바인딩된
id의 처리를, 모듈 밖에서도 항상 문법 오류를 보고하도록 변경됨.
더 알아보기
#%app— 프로시저 애플리케이션과 #%app- 확장 단계