2013-11-23 3 views
2

매크로와 일치하는 패턴을 쓰려고합니다. 나는별로 멀지 않았지만 나는 이미 혼란 스럽다. 테스트 코드는 다음과 같습니다.렉시 컬 범위 지정 및 구문 - 케이스

#!r6rs 

(import (for (rnrs base (6)) run expand) 
     (for (rnrs syntax-case (6)) expand) 
     (rnrs io simple (6))) 

(define-syntax matcher 
    (lambda (stx) 

    (define (parse-clauses c) 
     #'x) 

    (syntax-case stx() 
     ((_ c ...) 
     (with-syntax ((body (parse-clauses #'(c ...)))) 
     #'(lambda (x) body)))))) 

(write ((matcher) '(1 2 3))) (newline) 

출력 할 때 출력은 (1 2 3)입니다.

솔직히 말해서이 코드가 실패 할 것이라는 기대로이 코드를 작성했습니다. parse-clauses에서 반환 된 구문이 정의되지 않은 기호 x을 참조한다고 생각했습니다. 그러나 #'xparse-clauses에서 반환 된 것은 λ 식의 매개 변수 x을 참조합니다. 나는 이유를 모른다.

이 약간의 변형은 훨씬 더 혼란 스럽습니다.

#!r6rs 

(import (for (rnrs base (6)) run expand) 
     (for (rnrs syntax-case (6)) expand) 
     (rnrs io simple (6))) 

(define-syntax matcher 
    (lambda (stx) 

    (define (parse-clauses c) 
     (let ((x 1)) 
     #'x)) 

    (syntax-case stx() 
     ((_ c ...) 
     (with-syntax ((body (parse-clauses #'(c ...)))) 
     #'(lambda (x) body)))))) 

(write ((matcher) '(1 2 3))) (newline) 

이렇게하면 x: identifier used out of context in: x 오류가 발생합니다. 이 오류는 내가 이해, xparse-clauses에 로컬로 바인딩되어 있지만 오류가 그래서 그 범위 밖에서 참조를 사용하고 있습니다.

제가 말하고자하는 것은 두 번째 예제는 어휘 문맥이 중요하다는 것을 보여줍니다. 그러나 첫 번째 예에서는 x에 대한 어휘 바인딩이 없으므로 관련없는 바인딩을 참조하는 것이 어떻게 끝나나요?

너무 혼란스럽지 않고 모든 설명을 환영합니다.

라켓 5.3.6을 사용하고 있습니다.

답변

0

x은 동일한 매크로 확장 단계에서 도입 되었기 때문에 lambda 인수를 참조합니다. 매크로 시스템은 다른 단계에서 도입 된 식별자 만 구별합니다 (이 매크로가 다른 x을 도입하는 다른 매크로로 확장되는 경우). 다른 사람이 되십시오).

x는 컴파일 시간 변수 결합 ( parse-clauses는 컴파일 시간 함수)과 어떻게 든 람다의 x 방해 때문에 에러가 제 생각.