【问题标题】:Lisp: expand property name in macroLisp:在宏中扩展属性名称
【发布时间】:2017-12-16 21:25:22
【问题描述】:

考虑这个属性列表:

(defvar *some-variable* (list :foo "fooval" :bar "barval"))

这个简单的调用:

(getf *some-variable* :foo)

按预期产生"fooval"。我定义了一个宏,它应该做同样的事情,除了我可以传递任何属性的名称来检索:

(defmacro my-macro (property-name)
    `(getf *some-variable* :,property-name))

不幸的是,这样称呼它:

(my-macro 'foo)

结果为@​​987654326@。为什么?

【问题讨论】:

  • 使用 MACROEXPAND 进行调试。
  • @RainerJoswig:我已经尝试过了,但我仍然一无所知。
  • 它返回了什么?
  • 似乎没有人指出:,x 本质上是一个语法错误。您不能使用, 来拼接符号语法中的内容:这就像您说make-,foo 尝试创建一些符号一样虚假。如果你想在特定的包中构造符号,你必须做更多的工作。
  • @RainerJoswig 谢谢!我应该在发表评论之前尝试一下:我认为我认为符合标准的解释是 CLISP 的,但我实际上不确定,也许只是不清楚它是否合法。显然,它 做的是 OP 想要的。这种错误往往来自使用“字符串中的语言”宏系统,如(颤抖)Jinja2。

标签: macros lisp common-lisp clisp gnu-common-lisp


【解决方案1】:

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

(macroexpand-1 '(my-macro 'foo))
; ==> (getf *some-variable* :|| 'foo) ;
T

documentation for getf 表示如果你给它第四个参数,它就是没有找到键时的值。由于:||(关键字包中的空符号)不存在,它返回提供的默认foo

所以这里有一个函数可以满足你的需求:

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

(defparameter *test* 'foo)
(get-field *test*)
; ==> "fooval"

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

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

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

(get-mfield *test*)
; ==> nil

您可以使用纯文字,但您失去了 *test* 被视为变量而不是键 :*test* 的功能

【讨论】:

    猜你喜欢
    • 2013-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多