You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Lisp宏接收变量而非未加引号列表?字母算术求解器需求

解决字母算术求解器宏接收变量的问题

我懂你现在的困扰——你写的word-to-number宏目前只能处理字面量符号列表(比如直接写'(#\ #\E #\A #\S #\T)),但没法直接接收存储着符号列表的变量(比如你定义的east)。这是因为宏是在编译展开阶段工作的,原宏里的loop for symbol in symbols会试图在展开时遍历symbols的元素,但如果symbols是变量,此时它只是一个符号,不是实际的列表,自然会出错。

解决方案:让宏在运行时处理符号列表

我们需要修改宏的逻辑,把遍历符号列表的操作推迟到运行时,这样就能接收变量(或任何能返回符号列表的表达式)作为参数了。修改后的宏如下:

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

代码解释

  • symbols-expr现在可以是任何能在运行时求值为符号列表的表达式(比如变量名east,或者更复杂的表达式)。
  • 宏展开后会生成一段运行时代码:遍历symbols-expr求值后的列表,跳过空格字符,然后通过position找到每个符号在*symbol-positions中的索引,再从lst中取出对应的数字,最后传给tonumber。

测试示例

用你定义的变量测试:

(defparameter *symbol-positions* '(#\H #\T #\S #\R #\A #\U #\E #\O #\W #\N))
(defparameter num '(0 1 2 3 4 5 6 7 8 9))
(defparameter east '(#\ #\E #\A #\S #\T))

;; 现在可以直接传入变量east了
(word-to-number east num)

优化建议:提升查找效率

如果你的字母算术问题涉及很多符号,position函数每次遍历*symbol-positions列表会有点慢。可以预先构建一个哈希表,把字符映射到对应的索引,这样查找速度会快很多:

;; 预先构建字符到索引的哈希表
(defparameter *char-to-index* (make-hash-table))
(loop for idx from 0
      for char in *symbol-positions*
      do (setf (gethash char *char-to-index*) idx))

;; 修改后的宏
(defmacro word-to-number (symbols-expr lst)
  `(tonumber (loop for symbol in ,symbols-expr
                   unless (eql symbol #\ )
                   collect (nth (gethash symbol *char-to-index*) ,lst))))

这样每次查找字符对应的索引时,哈希表的gethash操作是O(1)的,比position的O(n)高效得多。

内容的提问来源于stack exchange,提问作者Gustav Bertram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:54:47