네임스페이스
네임스페이스 (Namespaces)
네임스페이스(namespace)를 만들고, 전환하고, 조작하는 프로시저들을 살펴볼게요. eval과 같은 프로시저에 네임스페이스를 넘겨 원하는 환경에서 코드를 실행할 수 있어요.
출처: Racket Reference
본문
네임스페이스 모델에 대한 기본 정보는 Namespaces를 참고하세요.
새 네임스페이스는 make-empty-namespace나 make-base-namespace 같은 프로시저로 만들어지며, 일급 네임스페이스 값을 돌려줘요. 네임스페이스는 current-namespace 파라미터 값을 설정하거나, eval·eval-syntax 같은 프로시저에 네임스페이스를 제공함으로써 사용돼요.
procedure
(namespace? v) → boolean?
v : any/c
v가 네임스페이스 값이면 #t를, 그렇지 않으면 #f를 돌려줘요.
procedure
(make-empty-namespace) → namespace?
비어 있는 새 네임스페이스를 만들어요. 그 모듈 레지스트리는 '#%kernel 같은 몇몇 내부·사전 정의 모듈에 대한 매핑만 담아요. 네임스페이스의 기본 위상(base phase)은 현재 네임스페이스의 기본 위상과 같아요. namespace-attach-module로 기존 네임스페이스의 모듈을 새 네임스페이스에 붙여요.
새 네임스페이스는 새 루트 네임스페이스와 연결돼요. 루트 네임스페이스는 돌려받은 네임스페이스와 같은 모듈 레지스트리를 가지며 기본 위상이 0이에요. 둘 다 기본 위상이 0이면 새 루트 네임스페이스는 돌려받은 네임스페이스와 같아요.
procedure
(make-base-empty-namespace) → namespace?
make-empty-namespace처럼 새 빈 네임스페이스를 만들지만, racket/base가 붙어 있어요. 네임스페이스의 기본 위상은 make-base-empty-namespace 함수가 만들어진 위상과 같아요.
procedure
(make-base-namespace) → namespace?
make-empty-namespace처럼 새 네임스페이스를 만들지만, racket/base가 붙어 있고 최상위 환경으로 require돼요. 네임스페이스의 기본 위상은 make-base-namespace 함수가 만들어진 위상과 같아요.
syntax
(define-namespace-anchor id)
id를 namespace-anchor->empty-namespace와 namespace-anchor->namespace에 사용할 수 있는 네임스페이스 앵커(anchor)에 바인딩해요.
이 폼은 최상위 컨텍스트나 모듈 컨텍스트에서만 사용할 수 있어요.
procedure
(namespace-anchor? v) → boolean?
v : any/c
v가 네임스페이스 앵커 값이면 #t를, 그렇지 않으면 #f를 돌려줘요.
procedure
(namespace-anchor->empty-namespace a) → namespace?
a : namespace-anchor?
앵커의 소스와 모듈 레지스트리·루트 네임스페이스를 공유하고, 기본 위상이 앵커가 만들어진 위상인 빈 네임스페이스를 돌려줘요.
앵커가 모듈 컨텍스트의 define-namespace-anchor 폼에서 온 것이라면, 소스는 포함하는 모듈이 인스턴스화되는 네임스페이스예요. 앵커가 최상위 콘텐츠의 define-namespace-anchor 폼에서 온 것이라면, 소스는 앵커 정의가 평가된 네임스페이스예요.
procedure
(namespace-anchor->namespace a) → namespace?
a : namespace-anchor?
앵커의 소스에 대응하는 네임스페이스를 돌려줘요.
앵커가 모듈 컨텍스트의 define-namespace-anchor 폼에서 온 것이라면, 결과는 앵커의 위상에서 모듈 본문을 위한 네임스페이스예요. 결과는 module->namespace로 얻는 네임스페이스와 같고, 모듈이 아직 이용 가능하지 않으면 비슷하게 이용 가능하게 만들어져요.
앵커가 최상위 콘텐츠의 define-namespace-anchor 폼에서 온 것이라면, 결과는 앵커 정의가 평가된 네임스페이스예요.
parameter
(current-namespace) → namespace?
(current-namespace n) → void?
n : namespace?
현재 네임스페이스를 결정하는 파라미터예요.
procedure
(namespace-symbol->identifier sym) → identifier?
sym : symbol?
심볼로 제한된 datum->syntax와 비슷해요. 결과 식별자의 어휘 정보는 현재 네임스페이스의 최상위 환경에 대응하고, 식별자는 소스 위치나 프로퍼티가 없어요.
procedure
(namespace-base-phase [namespace]) → exact-integer?
namespace : namespace? = (current-namespace)
namespace의 기본 위상을 돌려줘요.
procedure
(namespace-module-identifier [where]) → identifier?
where : (or/c namespace? exact-integer? #f) = (current-namespace)
where가 네임스페이스면 그 기본 위상에서, 그렇지 않으면 where 위상 레벨에서, 바인딩이 module인 식별자를 돌려줘요.
식별자의 어휘 정보는 (같은 위상 레벨에서) 완전히 확장된 코드에 나타나는 모든 구문 폼에 대한 바인딩을 담지만, 바인딩은 identifier-binding의 두 번째 요소가 보고하는 이름을 사용해요. 어휘 정보는 다른 바인딩도 포함할 수 있어요.
procedure
(namespace-variable-value sym
[use-mapping?
failure-thunk
namespace]) → any
sym : symbol?
use-mapping? : any/c = #t
failure-thunk : (or/c (-> any) #f) = #f
namespace : namespace? = (current-namespace)
namespace에서 sym의 값을, namespace의 기본 위상을 사용해 돌려줘요. 반환 값은 use-mapping?에 따라 달라져요:
use-mapping?가 참(기본값)이고,sym이 최상위 변수나 import된 변수(Namespaces 참고)에 매핑되면, 결과는sym을 표현식으로 평가하는 것과 같아요.sym이 구문이나 import된 구문에 매핑되면failure-thunk가 호출되거나exn:fail:syntax예외가 발생해요.sym이 정의되지 않은 변수나 초기화되지 않은 모듈 변수에 매핑되면failure-thunk가 호출되거나exn:fail:contract:variable예외가 발생해요.use-mapping?가#f면, 네임스페이스의 구문·import 매핑은 무시돼요. 대신namespace에서 이름이sym인 최상위 변수의 값이 돌려져요. 변수가 정의되지 않으면failure-thunk가 호출되거나exn:fail:contract:variable예외가 발생해요.
failure-thunk가 #f가 아니면, namespace-variable-value는 exn:fail:contract:variable이나 exn:fail:syntax 예외를 발생시키는 대신 failure-thunk를 호출해 반환 값을 만들어 내요.
procedure
(namespace-set-variable-value! sym
v
[map?
namespace
as-constant?]) → void?
sym : symbol?
v : any/c
map? : any/c = #f
namespace : namespace? = (current-namespace)
as-constant? : any/c = #f
기본 위상에서 namespace의 최상위 환경에 있는 sym의 값을 설정하고, 아직 정의되지 않았다면 sym을 정의해요.
map?가 참으로 제공되면, 네임스페이스의 식별자 매핑(Namespaces 참고)도 기본 위상에 대응하는 위상 레벨에서 조정되어, sym이 그 변수에 매핑돼요.
as-constant?가 참이면, v가 값으로 설치된 후 그 변수는 상수가 돼요(그래서 이후의 할당은 거부돼요).
패키지 base의 버전 6.90.0.14에서 변경됨: as-constant? 인자를 추가했어요.
procedure
(namespace-undefine-variable! sym
[namespace]) → void?
sym : symbol?
namespace : namespace? = (current-namespace)
기본 위상에서 namespace의 최상위 환경에 있는 sym 변수(있으면)를 제거해요. 네임스페이스의 식별자 매핑(Namespaces 참고)은 영향을 받지 않아요.
procedure
(namespace-mapped-symbols [namespace]) → (listof symbol?)
namespace : namespace? = (current-namespace)
네임스페이스의 기본 위상에 대응하는 위상 레벨에서, namespace의 변수·구문·import에 매핑된 모든 심볼의 리스트를 돌려줘요.
procedure
(namespace-require quoted-raw-require-spec
[namespace]) → void?
quoted-raw-require-spec : any/c
namespace : namespace? = (current-namespace)
namespace의 최상위 환경에서 quoted-raw-require-spec에 대응하는 import를, 최상위 #%require처럼 수행해요. quoted-raw-require-spec 인자는 모듈 경로를 포함하는, 인용된 raw-require-spec(#require용)에 대응하는 datum이거나, 해석된 모듈 경로일 수 있어요.
quoted-raw-require-spec 안의 모듈 경로는 current-load-relative-directory 또는 (전자가 #f면) current-directory를 기준으로 해석돼요. 현재 네임스페이스가 모듈 본문에 대응하더라도 마찬가지예요.
패키지 base의 버전 6.90.0.16에서 변경됨: namespace 선택 인자를 추가했어요.
procedure
(namespace-require/copy quoted-raw-require-spec
[namespace]) → void?
quoted-raw-require-spec : any/c
namespace : namespace? = (current-namespace)
모듈에서 내보낸 구문에 대해서는 namespace-require와 같지만, 네임스페이스의 기본 위상에서 내보낸 변수는 다르게 취급돼요. export의 현재 값이 namespace의 최상위 변수로 복사돼요.
패키지 base의 버전 6.90.0.16에서 변경됨: namespace 선택 인자를 추가했어요.
procedure
(namespace-require/constant quoted-raw-require-spec
[namespace]) → void?
quoted-raw-require-spec : any/c
namespace : namespace? = (current-namespace)
namespace-require와 같지만, 네임스페이스의 기본 위상에 있는 각 export 변수에 대해 export의 값이 불변(immutable)으로 만들어진 대응 최상위 변수로 복사돼요. 최상위 변수를 설정하지만, 대응하는 식별자는 import된 것으로 바인딩돼요.
패키지 base의 버전 6.90.0.16에서 변경됨: namespace 선택 인자를 추가했어요.
procedure
(namespace-require/expansion-time quoted-raw-require-spec
[namespace])
→ void?
quoted-raw-require-spec : any/c
namespace : namespace? = (current-namespace)
namespace-require와 같지만, 모듈의 transformer 부분만 namespace의 기본 위상에 대해 실행돼요. 즉 모듈은 단지 방문(visited)될 뿐 인스턴스화되지는 않아요(Module Expansion, Phases, and Visits 참고). 요구된 모듈이 이전에 인스턴스화된 적이 없으면, 모듈의 변수는 정의되지 않은 채로 남아요.
패키지 base의 버전 6.90.0.16에서 변경됨: namespace 선택 인자를 추가했어요.
procedure
(namespace-attach-module src-namespace
modname
[dest-namespace]) → void?
src-namespace : namespace?
modname : (or module-path? resolved-module-path?)
dest-namespace : namespace? = (current-namespace)
src-namespace(의 기본 위상)에서 modname이라는 이름의 인스턴스화된 모듈을 dest-namespace의 모듈 레지스트리에 붙여요.
modname 외에도, 그것이 (직접 또는 간접적으로) import하는 모든 모듈도 현재 네임스페이스의 모듈 레지스트리에 기록되고, 같은 위상의 인스턴스도 dest-namespace에 붙여져요(모듈 위상의 방문과 더 높거나 낮은 위상의 인스턴스는 붙지 않고, 온디맨드 방문에 이용 가능하게조차 되지 않아요). dest-namespace에서 모듈 호출의 인스펙터는 src-namespace의 호출 인스펙터와 같아요.
modname이 심볼이 아니면, 현재 모듈 이름 해석기가 경로를 해석하도록 호출되지만, 모듈은 로드되지 않아요. modname의 해석된 형태가 dest-namespace의 모듈 이름으로 사용돼요.
modname이 서브모듈이나 서브모듈이 있는 모듈을 가리키면, 모듈이 같은 최상위 모듈 안의 서브모듈과 독립적으로(즉 .zo 파일로) 바이트코드에서 로드되지 않는 한, 모듈의 최상위 모듈 안의 모든 서브모듈에 대한 선언도 dest-namespace에 붙어요.
modname이 src-namespace의 인스턴스화된 모듈을 가리키지 않거나, 붙여질 모듈 이름 중 어떤 것이 dest-namespace에 이미 다른 선언이나 같은 위상 인스턴스를 가지고 있으면, exn:fail:contract 예외가 발생해요.
src-namespace와 dest-namespace의 기본 위상이 같지 않으면 exn:fail:contract 예외가 발생해요.
namespace-require와 달리, namespace-attach-module은 모듈을 인스턴스화하지 않아요. 모듈 인스턴스를 소스 네임스페이스에서 대상 네임스페이스로 복사할 뿐이에요.
예시를 볼게요:
> (module food racket/base
(provide apple)
(define apple (list "pie")))
> (namespace-require ''food)
> (define ns (current-namespace))
> (parameterize ([current-namespace (make-base-namespace)])
(namespace-require ''food))
require: unknown module
module name: 'food
> (parameterize ([current-namespace (make-base-namespace)])
(namespace-attach-module ns ''food)
(namespace-require ''food)
(eq? (eval 'apple) apple))
#t
> (parameterize ([current-namespace (make-base-namespace)])
(namespace-attach-module-declaration ns ''food)
(namespace-require ''food)
(eq? (eval 'apple) apple))
#f
procedure
(namespace-attach-module-declaration src-namespace
modname
[dest-namespace]) → void?
src-namespace : namespace?
modname : module-path?
dest-namespace : namespace? = (current-namespace)
namespace-attach-module과 같지만, modname이 지정한 모듈은 src-namespace에서 선언만(반드시 인스턴스화될 필요는 없음) 되어 있으면 되고, 모듈은 dest-namespace에서 단지 선언만 돼요.
procedure
(namespace-unprotect-module inspector
modname
[namespace]) → void?
inspector : inspector?
modname : module-path?
namespace : namespace? = (current-namespace)
namespace의 모듈 레지스트리에 있는 modname이 참조하는 모듈 인스턴스의 인스펙터를, 현재 코드 인스펙터가 제어하도록 바꿔요. 주어진 inspector가 현재 namespace의 모듈 레지스트리에 있는 모듈의 호출을 제어해야 하며, 그렇지 않으면 인스펙터는 바뀌지 않아요. Code Inspectors도 참고하세요.
procedure
(namespace-module-registry namespace) → any
namespace : namespace?
주어진 네임스페이스의 모듈 레지스트리를 돌려줘요. 이 값은 eq?로 식별하는 데만 쓸모 있어요.
procedure
(namespace-call-with-registry-lock namespace
thunk) → any
namespace : namespace?
thunk : (-> any)
네임스페이스의 모듈 레지스트리에 대한 재진입 가능(reentrant) 잠금을 잡은 채 thunk를 호출해요.
네임스페이스 함수는 레지스트리 잠금을 자동으로 사용하지 않지만, 모듈을 로드하고 인스턴스화하는 스레드들 사이에서 namespace-call-with-registry-lock을 통해 사용해 내부 경쟁 조건을 피할 수 있어요. 이용 가능한 모듈의 온디맨드 인스턴스화도 잠금을 잡아요. Module Expansion, Phases, and Visits를 참고하세요.
패키지 base의 버전 8.1.0.5에서 추가됨.
procedure
(module->namespace mod [src-namespace]) → namespace?
mod :
(or/c module-path?
resolved-module-path?
module-path-index?)
src-namespace : namespace? = (current-namespace)
src-namespace의 모듈 레지스트리와 src-namespace의 기본 위상에 있는 인스턴스화된 모듈의 본문에 대응하는 네임스페이스를 돌려주고, src-namespace의 기본 위상에서 온디맨드 방문을 위해 모듈을 이용 가능하게 만들어요. 돌려받은 네임스페이스는 src-namespace와 같은 모듈 레지스트리를 가져요. 결과 네임스페이스에서 바인딩을 수정하면, 그 네임스페이스의 모듈을 require하는 모듈에서 보이는 바인딩이 바뀌어요.
최상위 require 표현식의 모듈 경로는 네임스페이스의 모듈을 기준으로 해석돼요. 새 provide 선언은 허용되지 않아요.
현재 코드 인스펙터가 src-namespace의 모듈 레지스트리에 있는 모듈의 호출을 제어하지 않으면 exn:fail:contract 예외가 발생해요. Code Inspectors도 참고하세요.
모듈이 선언될 때 compile-enforce-module-constants 파라미터가 참이었다면(모듈 선언 자체가 set!로 바인딩에 대한 할당을 포함하지 않는 한), 결과 네임스페이스의 바인딩은 수정될 수 없어요.
패키지 base의 버전 6.90.0.16에서 변경됨: src-namespace 선택 인자를 추가했어요.
procedure
(namespace-syntax-introduce stx [namespace]) → syntax?
stx : syntax?
namespace : namespace? = (current-namespace)
stx 같은 구문 객체를 돌려주되, namespace의 바인딩이 구문 객체의 어휘 정보(Syntax Objects 참고)에 포함돼요. 추가 컨텍스트는 구문 객체의 어휘 정보에 있는 기존 최상위 바인딩이나, 어휘 정보에 있는 기존·미래의 모듈 바인딩에 의해 덮어써져요.
패키지 base의 버전 6.90.0.16에서 변경됨: namespace 선택 인자를 추가했어요.
procedure
(module-provide-protected? module-path-index
sym) → boolean?
module-path-index : (or/c symbol? module-path-index?)
sym : symbol?
module-path-index의 모듈 선언이 sym을 정의하고 그것을 보호 없이 export하면 #f를, 그렇지 않으면 #t를 돌려줘요(#t는 그 심볼이 export되지 않은 정의, 보호된 export, 또는 모듈 안에서 전혀 정의되지 않은 식별자에 대응한다는 뜻일 수 있어요).
module-path-index 인자는 심볼일 수 있어요. 모듈 경로 인덱스에 대한 자세한 내용은 Compiled Modules and References를 참고하세요.
보통 module-provide-protected?의 인자는 identifier-binding이 만들어 내는 리스트의 처음 두 요소에 대응해요.
procedure
(variable-reference? v) → boolean?
v : any/c
v가 #%variable-reference가 만들어 내는 변수 참조이면 #t를, 그렇지 않으면 #f를 돌려줘요.
procedure
(variable-reference-constant? varref) → boolean?
varref : variable-reference?
varref가 나타내는 변수가 현재 값을 유지하면(즉 varref가 set!나 define으로 더 이상 수정될 수 없는 변수를 참조하면) #t를, 그렇지 않으면 #f를 돌려줘요.
procedure
(variable-reference->empty-namespace varref) → namespace?
varref : variable-reference?
varref가 인스턴스화된 네임스페이스와 모듈 선언·인스턴스를 공유하고, varref와 같은 위상인 빈 네임스페이스를 돌려줘요.
procedure
(variable-reference->namespace varref) → namespace?
varref : variable-reference?
varref가 모듈 레벨 변수를 참조하면, 결과는 참조된 변수의 위상에서 모듈 본문을 위한 네임스페이스예요. 결과는 module->namespace로 얻는 네임스페이스와 같고, 모듈이 아직 이용 가능하지 않으면 비슷하게 이용 가능하게 만들어져요.
varref가 최상위 변수를 참조하면, 결과는 참조된 변수가 정의된 네임스페이스예요.
procedure
(variable-reference->resolved-module-path varref)
→ (or/c resolved-module-path? #f)
varref : variable-reference?
varref가 모듈 레벨 변수를 참조하면, 결과는 그 모듈을 이름 짓는 해석된 모듈 경로예요.
varref가 최상위 변수를 참조하면 결과는 #f예요.
procedure
(variable-reference->module-path-index varref)
→ (or/c module-path-index? #f)
varref : variable-reference?
varref가 모듈 레벨 변수를 참조하면, 결과는 그 모듈을 이름 짓는 모듈 경로 인덱스예요.
varref가 최상위 변수를 참조하면 결과는 #f예요.
procedure
(variable-reference->module-source varref)
→ (or/c symbol? (and/c path? complete-path?) #f)
varref : variable-reference?
varref가 모듈 레벨 변수를 참조하면, 결과는 모듈의 소스를 이름 짓는 경로나 심볼이에요(보통은 해석된 모듈 경로와 같지만 항상 그런 것은 아니에요). 관련 모듈이 서브모듈이면, 결과는 둘러싸는 최상위 모듈의 소스에 대응해요.
varref가 최상위 변수를 참조하면 결과는 #f예요.
procedure
(variable-reference->phase varref) → exact-nonnegative-integer?
varref : variable-reference?
varref가 참조하는 변수의 위상을 돌려줘요.
procedure
(variable-reference->module-base-phase varref) → exact-integer?
varref : variable-reference?
varref가 참조하는 변수에 대해 모듈이 인스턴스화되는 위상을 돌려주고, varref의 변수가 모듈 안에 없으면 0을 돌려줘요.
모듈이 있는 변수의 경우, 변수가 모듈 안 위상 레벨 n에서 바인딩되면, 결과는 (variable-reference->phase varref)의 결과보다 n만큼 작아요.
procedure
(variable-reference->module-declaration-inspector varref)
→ inspector?
varref : variable-reference?
varref의 모듈에 대한 선언 인스펙터(Code Inspectors 참고)를 돌려줘요. 이때 varref는 (#%variable-reference)가 만들어 내는 익명 모듈 변수를 참조해야 해요.
procedure
(variable-reference-from-unsafe? varref) → boolean?
varref : variable-reference?
(반드시 참조된 변수는 아닌) 변수 참조 자체의 모듈이 unsafe 모드로 컴파일되면 #t를, 그렇지 않으면 #f를 돌려줘요. unsafe 모드는 linklet 인터페이스로 활성화하거나 모듈에 (#%declare #:unsafe)로 활성화할 수 있어요.
variable-reference-from-unsafe? 프로시저는 다음처럼 사용하기 위한 것이에요:
(variable-reference-from-unsafe? (#%variable-reference))
컴파일러가 이것을 리터럴 #t나 #f로 최적화할 수 있어요(둘러싸는 모듈이 unsafe 모드로 컴파일 중이냐 아니냐에 따라).
패키지 base의 버전 6.12.0.4에서 추가됨.