Common Lisp Backquote / Backtick: как использовать?

, у меня возникают проблемы с чтением обратных кавычек 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 способов заставить макросы для генерации кода для правильной оценки аргументов во время выполнения были бы очень признательны.

9
задан Rainer Joswig 26 June 2011 в 20:45
поделиться