该宏的目的是创建一个宏,该宏为访问关联列表的特定键提供名称。

(defmacro generate-accessor (key-symbol prefix)
  (let ((mac-name
          (intern (string-upcase (concatenate 'string
                                              prefix "-"
                                              (string key-symbol))))))
    `(defmacro ,mac-name (alis) `(assoc ,',key-symbol ,alis))))

所以当我尝试-
CL-USER> (generate-accessor 'a "alist")
; ERROR> 'A cannot be coerced to a string.

但是...
CL-USER> (string 'a)
; RESULT> "A"

因此,我再次尝试使用SYMBOL-NAME将符号强制转换为字符串
(defmacro generate-accessor (key-symbol prefix)
  (let ((mac-name
          (intern (string-upcase (concatenate 'string
                                              prefix "-"
                                              (symbol-name key-symbol))))))
    `(defmacro ,mac-name (alis) `(assoc ,',key-symbol ,alis))))

这次我尝试-
CL-USER> (generate-accessor 'a "alist")
; ERROR> The value 'A is not of type SYMBOL.

但是...
CL-USER> (symbol-name 'a)
; RESULT>"A"
CL-USER> (symbolp 'a)
; RESULT>T

每当我在宏之外使用'a时,它就会像我期望的那样作为符号自动插入。但是当我将'a传递给宏时,它以引用的块的形式到达。我不明白为什么不对其进行评估,尤其是在反引号开始之前的某个时刻。我知道我不了解Lisp的一些基本知识,但现在不知道如何看待。

最佳答案

'a(quote a)的简写,它是您要传递给宏的列表。宏参数不进行评估,而是按原样传递。当用作函数(而不是宏)的参数时,首先评估(quote a),评估(quote a)的结果是符号a。例如,考虑一下

(list 'a)           ===
(list (quote a))
; => (a)


'('a)               ===
'((quote a))        ===
(quote ((quote a)))
; => ((quote a)) ;; which may also be printed ('a)

对宏使用符号参数的示例

根据注释中的请求,这是一个类似于defstruct的宏,该宏创建一些合并结构名称的函数。
(defmacro my-defstruct (name slot)
  "A very poor implementation of defstruct for structures
that have exactly one slot"
  (let ((struct-name (string name))
        (slot-name (string slot)))
    `(progn
       (defun ,(intern (concatenate 'string (string '#:make-) struct-name)) (value)
         (list value))
       (defun ,(intern (concatenate 'string (string struct-name) "-" slot-name)) (structure)
         (car structure)))))

这是例如(my-defstruct foo bar)扩展为:
CL-USER> (pprint (macroexpand '(my-defstruct foo bar)))

(PROGN
 (DEFUN MAKE-FOO (VALUE) (LIST VALUE))
 (DEFUN FOO-BAR (STRUCTURE) (CAR STRUCTURE)))

使用示例:
CL-USER> (my-defstruct foo bar)
FOO-BAR
CL-USER> (make-foo 34)
(34)
CL-USER> (foo-bar (make-foo 34))
34

07-24 15:05