최상위 레벨 폼 확장

최상위 레벨 폼 확장 (Expanding Top-Level Forms)

매크로를 프로그래밍 방식으로 확장하려면 expand 계열의 함수를 사용해요. 이 문서에서는 expand, expand-once, expand-to-top-form과 syntax 객체용 변형들, 그리고 확장된 모듈 정보에 대해 설명합니다.

출처: Racket Reference

본문

procedure
(expand top-level-form [insp]) → syntax?
  top-level-form : any/c
  insp : inspector? = (current-code-inspector)

top-level-form의 모든 비-기본(non-primitive) 구문을 확장하고, "Fully Expanded Programs"에 의해 지정된 문법을 만족하는 핵심 폼만 포함하는 확장된 폼에 대한 구문 객체를 반환합니다.

top-level-form이 확장되기 전에, 그 어휘적 컨텍스트는 eval에서처럼 namespace-syntax-introduce로 강화됩니다. 반환된 구문 객체를 인쇄 가능한 datum으로 변환하려면 syntax->datum을 사용하세요.

insp가 원래의 코드 인스펙터(즉, Racket이 시작될 때의 (current-code-inspector) 값)가 아니면, 결과 구문 객체는 테인트(taint)됩니다.

모듈에 expand를 사용하는 예시입니다:

(parameterize ([current-namespace (make-base-namespace)])
  (expand
   (datum->syntax
    #f
    '(module foo scheme
       (define a 3)
       (+ a 4)))))

최상위 레벨이 아닌 폼에 expand를 사용하는 예시입니다:

(define-namespace-anchor anchor)
(parameterize ([current-namespace
                (namespace-anchor->namespace anchor)])
  (expand
   (datum->syntax
    #f
    '(delay (+ 1 2)))))

base 패키지의 8.2.0.4 버전에서 변경됨: insp 인자와 테인팅이 추가되었습니다.

procedure
(expand-syntax stx [insp]) → syntax?
  stx : syntax?
  insp : inspector? = (current-code-inspector)

(expand stx insp)와 같지만, 인자가 구문 객체여야 하고, 확장 전에 어휘적 컨텍스트가 강화되지 않습니다.

base 패키지의 8.2.0.4 버전에서 변경됨: insp 인자와 테인팅이 추가되었습니다.

procedure
(expand-once top-level-form [insp]) → syntax?
  top-level-form : any/c
  insp : inspector? = (current-code-inspector)

top-level-form을 부분적으로 확장하고, 부분적으로 확장된 표현식에 대한 구문 객체를 반환합니다. 확장 메커니즘의 한계 때문에 일부 컨텍스트 정보가 유실될 수 있습니다. 특히, 결과에 대해 expand-once를 호출하면 expand를 통한 확장과 다른 결과가 나올 수 있습니다.

top-level-form이 확장되기 전에, 그 어휘적 컨텍스트는 eval에서처럼 namespace-syntax-introduce로 강화됩니다.

insp 인자는 expand에서처럼 결과가 테인트될지 여부를 결정합니다.

base 패키지의 8.2.0.4 버전에서 변경됨: insp 인자와 테인팅이 추가되었습니다.

procedure
(expand-syntax-once stx [insp]) → syntax?
  stx : syntax?
  insp : inspector? = (current-code-inspector)

(expand-once stx)와 같지만, 인자가 구문 객체여야 하고, 확장 전에 어휘적 컨텍스트가 강화되지 않습니다.

base 패키지의 8.2.0.4 버전에서 변경됨: insp 인자와 테인팅이 추가되었습니다.

procedure
(expand-to-top-form top-level-form [insp]) → syntax?
  top-level-form : any/c
  insp : inspector? = (current-code-inspector)

top-level-form을 부분적으로 확장해서 가장 바깥쪽 구문 폼을 드러냅니다. 이 부분 확장은 주로 begin의 최상위 사용을 탐지하는 데 유용합니다. expand-once의 결과와 달리, expand-to-top-form의 결과를 expand로 확장하면 원래 구문에 expand를 사용한 것과 같은 결과가 나옵니다.

stx-or-sexpr이 확장되기 전에, 그 어휘적 컨텍스트는 eval에서처럼 namespace-syntax-introduce로 강화됩니다.

insp 인자는 expand에서처럼 결과가 테인트될지 여부를 결정합니다.

base 패키지의 8.2.0.4 버전에서 변경됨: insp 인자와 테인팅이 추가되었습니다.

procedure
(expand-syntax-to-top-form stx [insp]) → syntax?
  stx : syntax?
  insp : inspector? = (current-code-inspector)

(expand-to-top-form stx)와 같지만, 인자가 구문 객체여야 하고, 확장 전에 어휘적 컨텍스트가 강화되지 않습니다.

base 패키지의 8.2.0.4 버전에서 변경됨: insp 인자와 테인팅이 추가되었습니다.

확장된 모듈에 대한 정보 (Information on Expanded Modules)

확장된 모듈 선언에 대한 정보는 구문 객체에 붙는 일련의 구문 속성들("Syntax Object Properties" 참고)에 저장됩니다:

  • 'module-body-context — 모듈의 내부에 해당하는 어휘 정보를 가진 구문 객체. 확장의 바깥쪽 가장자리 스코프(outside-edge scope)와 안쪽 가장자리 스코프(inside-edge scope)를 포함하므로, 이 구문 객체는 원래 모듈 본문에 존재하고 어떤 매크로의 조작에도 접근할 수 없는 식별자를 시뮬레이션합니다. 그래서 그 어휘 정보에는 모듈의 임포트와 정의에 대한 바인딩이 포함됩니다.

    base 패키지의 6.4.0.1 버전에서 추가됨.

  • 'module-body-inside-context — 어휘 컨텍스트 없이 시작해서 매크로 안으로 이동된 식별자에 해당하는 어휘 정보를 가진 구문 객체. 그래서 확장의 안쪽 가장자리 스코프만 포함합니다.

    base 패키지의 6.4.0.1 버전에서 추가됨.

  • 'module-body-context-simple? — 불리언. #t는 모듈 본문의 바인딩('module-body-inside-context 속성 값의 어휘 정보에 기록된 것)이, for-syntax, for-meta, for-template으로 임포트된 것을 포함해 모듈에 직접 임포트된 모듈들로부터 직접 재구성될 수 있음을 나타냅니다.

    base 패키지의 6.4.0.1 버전에서 추가됨.

    base 패키지의 7.0 버전에서 변경됨: 'module-variable-provides, 'module-syntax-provides, 'module-indirect-provides, 'module-indirect-for-meta-provides 속성이 제거되었습니다.

더 알아보기