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 (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 参数的变量? ,symbols 不起作用,`(,@symbols) 也不起作用

最佳答案

当你这样做时:

(word-to-number east num)

宏扩展器被调用,参数为 eastnum 。它们不会是您宏的列表和数字。仅对于生成的代码,它们才会在产生值的上下文中进行评估。

宏是语法转换。例如。

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

; ==

(if p1
    c1
    (if p2 
        c2
        a))

不管是p1(< a b)my-boolean-value 。宏只是将表达式放置在那里,而不必知道什么 a , bmy-boolean-value是。

所以告诉我.. (word-to-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))))

更新

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

您可能会注意到我正在存储 lst在变量 clst 中我在评估 symbols 后这样做。原因是,当您期望对参数求值时,您期望它们按顺序求值并且仅求值一次,除非重复求值是像 loop 这样的宏的功能。做。例如。这应该只打印一次“哦,快乐的一天”:

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

关于common-lisp - 我的宏如何采用变量而不是不带引号的列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49661224/

相关文章:

common-lisp - SBCL:将 Hunchentoot 应用程序部署为可执行文件

common-lisp - 在 ECL 上指定外部格式

format - LISP:(格式)仅在成功(读取)后打印

macros - 在宏中,我可以让 ,var 评估为空白/无吗?

lisp - 帮助减少一个 Lisp 函数

common-lisp - 为什么 SBCL 提示 setf?

lisp - CONS 对象可以用作哈希表的键吗?

emacs - Lisp 源代码文件本身是列表吗?

linux - 在我的 linux 机器上安装 lisp

list - 将项目替换为列表中的每个出现项