Lisp:在宏中扩展属性名称

mat*_*lat 1 lisp macros clisp common-lisp gnu-common-lisp

考虑这个属性列表:

(defvar *some-variable* (list :foo "fooval" :bar "barval"))
Run Code Online (Sandbox Code Playgroud)

这个简单的电话:

(getf *some-variable* :foo)
Run Code Online (Sandbox Code Playgroud)

收益率"fooval"如预期.我定义了一个宏应该做同样的事情,除了我可以传递任何属性的名称来检索:

(defmacro my-macro (property-name)
    `(getf *some-variable* :,property-name))
Run Code Online (Sandbox Code Playgroud)

不幸的是,这样称呼它:

(my-macro 'foo)
Run Code Online (Sandbox Code Playgroud)

结果FOO.为什么?

Syl*_*ter 5

你为什么不亲自检查一下:

(macroexpand-1 '(my-macro 'foo))
; ==> (getf *some-variable* :|| 'foo) ;
T
Run Code Online (Sandbox Code Playgroud)

对文件getf说,如果你给它一个第四个参数是该值时,找不到键.由于:||(关键字包中的空符号)不存在,因此返回提供的默认值foo.

所以这是一个能够做你想要的功能:

(defun get-field (name)
 (getf *some-variable* 
       (intern (symbol-name name) "KEYWORD")))

(defparameter *test* 'foo)
(get-field *test*)
; ==> "fooval"
Run Code Online (Sandbox Code Playgroud)

使其成为宏的唯一原因是使其成为语法,语法和函数之间的主要区别在于不评估参数.

(defmacro get-mfield (name)
  `(get-field ',name))

(get-mfield foo)
; ==> "fooval"

(get-mfield *test*)
; ==> nil
Run Code Online (Sandbox Code Playgroud)

你会得到文字裸露,但你失去了*test*被视为变量而不是关键的特征:*test*