Common lisp 我的宏如何接受变量而不是不带引号的列表?

Common lisp 我的宏如何接受变量而不是不带引号的列表?,common-lisp,Common Lisp,我正在构建一个字母解算器,我想制作一个宏,将数字替换为符号模板 以下是一个独立的示例: (defparameter *symbol-positions* '(#\H #\T #\S #\R #\A #\U #\E #\O #\W #\N)) (defmacro word-to-number (symbols lst) `(tonumber (list ,@(loop for symbol in symbols when (not (eq

我正在构建一个字母解算器,我想制作一个宏,将数字替换为符号模板

以下是一个独立的示例:

(defparameter *symbol-positions* '(#\H #\T #\S #\R #\A #\U #\E #\O #\W #\N))

(defmacro word-to-number (symbols lst)
  `(tonumber (list ,@(loop for symbol in symbols
                           when (not (eql symbol #\ ))
                             collect `(nth ,(position symbol *symbol-positions*) ,lst )))))

(defparameter num '(0 1 2 3 4 5 6 7 8 9))
(defparameter east '(#\  #\E #\A #\S #\T))
以下调用有效:

(word-to-number (#\  #\E #\A #\S #\T) num)
但这一条没有:

(word-to-number east num) ;=> The value EAST is not of type LIST
有没有办法修改宏以获取符号参数的变量,符号不起作用,`、@symbols

当您执行以下操作时,符号也不起作用:

(word-to-number east num)
调用宏扩展器时,参数为east和num。它们不会是宏的列表和编号。只有对于生成的代码,才会在生成值的上下文中对其进行求值

宏是语法转换。例如

(cond (p1 c1)
      (p2 c2)
      (t a))

; ==

(if p1
    c1
    (if p2 
        c2
        a))
不管p1是 那么告诉我。。从word到number east num的扩展应该是什么样子?也许它根本不应该是宏?例如

(defun word-to-number (symbols lst)
  (tonumber (loop :for symbol :in symbols
                  :when (not (eql symbol #\ ))
                  :collect (nth (position symbol *symbol-positions*) lst))))
更新

您可能会注意到,我将lst存储在变量clst中,并在计算符号后执行此操作。原因是,当您希望对参数求值时,您希望参数按顺序求值,并且只求值一次,除非重复求值是宏的一个特性,就像循环一样。这应该只打印一次哦,快乐的一天:

(word-to-number (progn (princ "Oh") east) (progn (princ ", happy day!") num))

我是否可以重写宏,将east作为符号插入到符号现在所在的位置?num替换有效。您的意思是返回与我的函数相同的代码,并用符号和表达式替换lst?舒尔,但你不会因此得到任何好处。通常你用宏来延迟参数的计算,这样你就可以了解代码模式。如果你能告诉我怎么做的话,我很乐意。不是因为我将使用它,而是因为它将帮助我理解反勾号在函数和宏中的工作方式之间的区别。@GustavBertram反勾号在函数和宏中的行为没有区别。宏以代码aka list结构作为参数调用其宏函数。结果应该是代码ni数据表示,lisp系统只是在运行之前(通常是在函数创建时)用生成的代码替换宏调用。事实上,您可以创建一个执行宏任务的函数,并使用相同的参数从宏调用它。易于测试单词到数字impl'east'num
(word-to-number (progn (princ "Oh") east) (progn (princ ", happy day!") num))