, у меня возникают проблемы с чтением обратных кавычек Lisp Каждый раз, когда я пытаюсь написать макрос, который, кажется, требует использования встроенных обратных кавычек (например, `(w, x ,, y)
из ANSI Common Lisp Пола Грэма, стр. 399), я не могу понять, как написать свой код таким образом, чтобы он компилировался. Обычно мой код получает целую цепочку ошибок, которой предшествует фраза «Запятая не внутри обратной кавычки». Может ли кто-нибудь дать рекомендации по написанию кода что будет правильно оценивать?
В качестве примера мне сейчас нужен макрос, который принимает форму, описывающую правило в форме '(значение индекса-столбца имени функции)
и генерирует лямбда-предикат body, чтобы определить, удовлетворяет ли элемент, проиндексированный column-index
для конкретной строки правилу. Если я вызвал этот макрос с правилом [119021 9] '(<1 2) , я бы хотел, чтобы было сгенерировано лямбда-тело, которое выглядит следующим образом:
(lambda (row)
(< (svref row 1) 2))
Лучший удар, который я могу сделать, это следующий:
(defmacro row-satisfies-rule (rule)
(let ((x (gensym)))
`(let ((,x ,rule))
(lambda (row)
(`,(car ,x) (svref row `,(cadr ,x)) `,(caddr ,x))))))
После оценки SBCL изрыгает следующий отчет об ошибке:
; in: ROW-SATISFIES-RULE '(< 1 2)
; ((CAR #:G1121) (SVREF ROW (CADR #:G1121)) (CADDR #:G1121))
;
; caught ERROR:
; illegal function call
; (LAMBDA (ROW) ((CAR #:G1121) (SVREF ROW (CADR #:G1121)) (CADDR #:G1121)))
; ==>
; #'(LAMBDA (ROW) ((CAR #:G1121) (SVREF ROW (CADR #:G1121)) (CADDR #:G1121)))
;
; caught STYLE-WARNING:
; The variable ROW is defined but never used.
; (LET ((#:G1121 '(< 1 2)))
; (LAMBDA (ROW) ((CAR #:G1121) (SVREF ROW (CADR #:G1121)) (CADDR #:G1121))))
;
; caught STYLE-WARNING:
; The variable #:G1121 is defined but never used.
;
; compilation unit finished
; caught 1 ERROR condition
; caught 2 STYLE-WARNING conditions
#<FUNCTION (LAMBDA (ROW)) {2497F245}>
Как я могу написать макросы для генерации нужного мне кода, и, в частности, как реализовать row -isfies-rule
?
Используя идеи от Ivijay и schemeulus , Я изменил макрос так, чтобы он компилировался и работал, даже позволяя передавать формы в качестве аргументов. Он работает немного иначе, чем изначально запланированный мной макрос, поскольку я определил, что включение строки
в качестве аргумента сделано для более плавного кода. Однако это уродливо, как грех. Кто-нибудь знает, как очистить его, чтобы он выполнял то же самое без вызова eval
?
(defmacro row-satisfies-rule-p (row rule)
(let ((x (gensym))
(y (gensym)))
`(let ((,x ,row)
(,y ,rule))
(destructuring-bind (a b c) ,y
(eval `(,a (svref ,,x ,b) ,c))))))
Кроме того, объяснение чистых, Lispy способов заставить макросы для генерации кода для правильной оценки аргументов во время выполнения были бы очень признательны.