일부 I/O 관련 변수가 수정 된 경우 format
을 사용한 접근 방식은 전혀 작동하지 않습니다. 심볼 이름을 생성하기 위해 format
을 사용하는 것은 일반적으로 꽤 부서지기 쉽고 이식성이 없습니다. 이 은으로 해결하기가 까다로울뿐 아니라 역 인용 부호 대신 목록 구성으로 접근하는 것이 더 쉬울 수도 있습니다. 예를 들어,이 경우 우리는 할 수 :
(defmacro definline (name variables &body body)
(list 'define-compiler-macro name variables
`(list* 'let (list ,@(mapcar (lambda (variable)
`(list (quote ,variable) ,variable))
variables))
',body)))
이 작동되도록 :
CL-USER> (pprint (macroexpand-1 '(definline foobar (a b)
(print "foobar")
(+ a b))))
(DEFINE-COMPILER-MACRO FOOBAR
(A B)
(LIST* 'LET (LIST (LIST 'A A) (LIST 'B B)) '((PRINT "foobar") (+ A B))))
내가 뭔가를 잘못 읽고있어 않는 한, 같은 결과로해야하는 :
(define-compiler-macro foobar (a b)
`(let ((a ,a) (b ,b))
(print "foobar")
(+ a b)))
backquotes 만 사용하여 후자의 양식을 생성하는 것이 반드시 가능하다고 생각하지 않습니다. 문제는 사양이 역 인용 부호가 구현되는 방법을 정확하게 정의하지 않기 때문에 구현 이 다음은 확장을 쓸 수있는 방법으로 그것을 구현 않는 경우가
(define-compiler-macro foobar (a b)
(backquote (let ((a (unquote a))
(b (unquote b)))
(print "foobar")
(+ a b)))
같은만큼 간단하지 것입니다 그 유형의 출력을 생성합니다. 구현에서 그러한 보증을 얻지 못한다면 상위 계층에 주입해야하는 "쉼표 변수"를 얻을 수있는 방법이 없다고 생각합니다. 그것은 분명이 점을 만들기 위해 열심히하지만이 시도 볼 수 있습니다
같은 결과를 생성합니다
(defmacro definline (name variables &body body)
`(define-compiler-macro ,name ,variables
`(let ,',(mapcar (lambda (variable)
`(,variable (unquote ,variable)))
variables)
,@',body)))
: SBCL이 정상으로 역 인용 부호를 대체하기 위해 이미 충분히 스마트 것을
(DEFINE-COMPILER-MACRO FOOBAR
(A B)
'(LET ((A (UNQUOTE A)) (B (UNQUOTE B)))
(PRINT "foobar")
(+ A B)))
공지 사항 따옴표로 묶지 않아야합니다. mapcar
은 쉼표가 구현 된 방법이 지정되어 있지 않기 때문에 쉼표가있는 코드를 생성 할 수 없으며 2.4.7 Comma에 따르면 "쉼표는 역 인용 부호 표현".나는 그것이 당신의 최선의 선택 같은 것을 것을 의미한다고 생각 :
(defmacro definline (name variables &body body)
`(define-compiler-macro ,name ,variables
`(let ,(mapcar 'list
',variables
(list ,@variables))
,@',body)))
이것의 확장은 다른 구현에 따라 다를 것입니다 만, SBCL에 그것의 :
는 CCL에
(DEFINE-COMPILER-MACRO FOOBAR (A B)
`(LET (SB-IMPL::BACKQ-COMMA (MAPCAR 'LIST '(A B) (LIST A B)))
(PRINT "foobar")
(+ A B)))
당신이 얻을 :
CLISP에서
(DEFINE-COMPILER-MACRO FOOBAR (A B)
(LIST* 'LET
(LIST* (MAPCAR 'LIST '(A B) (LIST A B))
'((PRINT "foobar") (+ A B)))))
:
(DEFINE-COMPILER-MACRO FOOBAR (A B)
(CONS 'LET
(CONS (MAPCAR 'LIST '(A B) (LIST A B)) '((PRINT "foobar") (+ A B)))))
생성 된 컴파일러 매크로 함수를 호출합니다. "(funcall (컴파일러 매크로 함수 'foobar)'(foobar 10 11)())"매크로 확장 -1 이외에 출력을 확인하는 데 유용한 도구가 될 수 있습니다. –
훌륭한 설명 주셔서 감사합니다! – asm