2013-02-27 6 views
1

매크로에 전달 된 매개 변수가 평가되는 방법에 대한 의문점이 있습니다. 자세한 내용은 아래를 참조하십시오.매크로 본문에 전달 된 매개 변수의 평가

이 매크로는

(defmacro test-macro (xlist) 
    `(* ,@xlist)) 

을 정의하고이 글로벌 변수 (defvar *test-list* '(1 100 2 200))가된다.

value *TEST-LIST* is not of the expected type LIST. 
    [Condition of type TYPE-ERROR] 

을하지만 기능이로 변경되었을 경우, 목록 (1 100 2 200)을 반환합니다

(defmacro test-macro (xlist) 
    `(,@xlist)) ;; removed the * operator 

(test-macro *test-list*)

을 반환 -

*test-list*이 매크로 (test-macro *test-list*)에 전달되면이 오류가 반환됩니다.

제 생각에는 ,@xlist이 첫 번째 경우에 평가되지 않는 것입니다. 즉 * 연산자가 적용될 때입니다. 어떤 도움을 주셔서 감사합니다.

답변

4

매크로를 디버깅 할 때 올바른 방법은 macroexpand을 사용하고 매크로 폼을 평가하지 않는 것입니다. 예 : 귀하의 경우 :

(defmacro test-macro1 (xlist) `(* ,@xlist)) 
(macroexpand '(test-macro1 foo)) 
==> (* . FOO) 
(defmacro test-macro2 (xlist) `(,@xlist)) 
(macroexpand '(test-macro2 foo)) 
==> FOO 

아마도 원하는 것은 아닙니다.

+0

많은 감사. 매크로 엑스 팬드는 매우 유용합니다 .. – 5Fists

+0

@ 5fists 슬라임에 macroexpand 단축키가 있습니다. 그것, 1 슬림을위한 –

3

매크로가 프리 프로세서이라는 혼란이 있습니다. 런타임 값을 알 수있는 기본 제공 메커니즘이 없습니다. 당신이 용어를 사용 그래서 :

매크로가 보는 식별자 test-list 모든 것을
(test-macro test-list) 

: 그것은 모르는 선행 런타임 값이 소스 프로그램이 변수 식별자를 사용하는 경우에만 것을 목록입니다.

매크로는 소스의 소스 재 작성기로, 프로그램의 다이나믹스에 대해 알지 못합니다. 똑똑한 컴파일러는 테스트 목록이 상수이고 인라이닝을 수행 할 수 있지만 매크로 확장기는 영리하지 못하다는 것을 알 수 있습니다.

(defmacro test-macro (xlist) 
    (cond 
    (;; If we see test-macro is being used with a quoted list of things 
    ;; then we can rewrite that statically. 
    (and (pair? xlist) 
      (eq? (car xlist) 'quote) 
      (list? (cadr xlist))) 
    `(list 'case-1 (* ,@(cadr xlist)))) 

    (;; Also, if we see test-macro is being used with "(list ...)" 
    ;; then we can rewrite that statically. 
    (and (pair? xlist) 
      (eq? (car xlist) 'list)) 
    `(list 'case-2 (* ,@(cdr xlist)))) 

    (else 
    ;; Otherwise, do the most generic thing: 
    `(list 'case-3 (apply * ,xlist))))) 



;; This hits the first case: 
(test-macro '(3 4 5)) 

;; ... the second case: 
(test-macro (list 5 6 7)) 

;; ... and the third case: 
(defvar test-list '(1 100 2 200)) 
(test-macro test-list) 

두 번째 버전에 관하여 : 당신이 할 수있는 일

은 아마이 같은 것입니다 매크로 :

(defmacro test-macro (xlist) 
    xlist) 
:

(defmacro test-macro (xlist) 
    `(,@xlist)) 

가 동일하다

그래서 당신은 첫 번째 버전에서받은 오류가 표시되지 않습니다.

+0

그런 세부 사항에서 설명 주셔서 감사합니다. 코드에서 사용한 함수 중 일부는 내가 사용하고있는 Common Lisp 구현에서 사용할 수 없습니다. 코드를 완전히 이해한다고 말할 수는 없지만 Lisp을 배울 때 매우 도움이되는 중요한 점은 없습니다. 나는 갈 길이 멀다. :) – 5Fists

관련 문제