Silvio Mayolo
Silvio Mayolo

Reputation: 70277

Defmacro that expands to defsetf

I'm having some trouble with some nested backquotes in CL. I'm trying to create a macro define-access that takes two parameters, F and A. define-access should define a function and setf expansion for symbol F that acts just like the respective function and setf for A. The current code is as follows.

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

The problem arises at the bottom, with the nested backquote.

The desired behavior of define-access is as follows.

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

But right now, according to macroexpand-1, I'm getting the following (line breaks added for sanity).

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

What am I not understanding about the backquote operator, or how should I approach this sort of problem?

Upvotes: 2

Views: 106

Answers (1)

Barmar
Barmar

Reputation: 781058

You need another comma before A in the nested backquote, so it expands to the value of the variable outside the outside the outer backquote. And then it needs to be quoted to keep from evaluating that as a variable. So it becomes ,',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)))))

DEMO

Upvotes: 3

Related Questions