Defmacro, расширяемый до defsetf

У меня проблемы с вложенными обратными кавычками в CL. Я пытаюсь создать макрос define-access, который принимает два параметра: F и A. define-access должен определять функцию и расширение setf для символа F, которое действует так же, как соответствующая функция и setf для A. Текущий код выглядит следующим образом.

(defmacro define-access (F A)
  (let ((X (gensym))
        (Y (gensym)))
    `(progn
       (defun ,F (,X)
         (,A ,X))
       (defsetf ,F (,X) (,Y)
         `(setf (,A ,,X) ,,Y)))))

Проблема возникает внизу, с вложенной обратной кавычкой.

Желаемое поведение define-access следующее.

(define-access fname car)
=> (progn (defun fname (x) (car x))
          (defsetf fname (x) (y) `(setf (first ,x) ,y)))

Но прямо сейчас, согласно macroexpand-1, я получаю следующее (для здравого смысла добавлены разрывы строк).

(PROGN (DEFUN FNAME (#:G22490) (CAR #:G22490))
       (DEFSETF FNAME (#:G22490) (#:G22491)
           (LIST 'SETF (LIST A #:G22490) #:G22491)))

Что я не понимаю в операторе обратной кавычки, или как мне подойти к подобной проблеме?


person Silvio Mayolo    schedule 30.01.2015    source источник
comment
Вы знаете, что define-access идентично сокращенной форме defsetf, верно? (defsetf fname car)   -  person Barmar    schedule 31.01.2015
comment
К вашему сведению, ваш макрос используется (define-access fname car), а не (define-access (fname car))   -  person Barmar    schedule 31.01.2015
comment
@Barmar Верно, извини. Исправлено. К счастью, расширение все равно было правильным.   -  person Silvio Mayolo    schedule 31.01.2015
comment
@Barmar Это? defsetf (насколько я знал) определил функцию записи, которая будет вызываться, когда setf используется в геттере, а не синоним (т.е. (defsetf car rplaca) будет определять что-то близкое к setf car)   -  person Silvio Mayolo    schedule 31.01.2015
comment
Простите, вы правы.   -  person Barmar    schedule 31.01.2015


Ответы (1)


Вам нужна еще одна запятая перед A во вложенной обратной кавычке, чтобы она расширилась до значения переменной за пределами внешней обратной кавычки. И затем его нужно указать, чтобы не оценивать это как переменную. Таким образом становится ,',A

(defmacro define-access (F A)
  (let ((X (gensym))
        (Y (gensym)))
    `(progn
       (defun ,F (,X)
         (,A ,X))
       (defsetf ,F (,X) (,Y)
         `(setf (,',A ,,X) ,,Y)))))

ДЕМО

person Barmar    schedule 30.01.2015
comment
Хм ... это похоже на то, что я ищу, но я получаю, что переменная CAR не имеет значения при попытке использовать расширитель setf. - person Silvio Mayolo; 31.01.2015
comment
Исправьте это. С вашим новым редактированием он работает безупречно. Большое тебе спасибо. - person Silvio Mayolo; 31.01.2015