lisp 宏扩展:不是 LIST 类型错误

问题描述 投票:0回答:1

我有一个读取文件的宏 其格式如下: (水 50) (氧气50) ...

宏看起来像这样:

(defmacro readextracttolist (filevar filename nthmember listname)
  (list 'progn 
    (list 'defparameter filevar (list 'open filename))
    (list 'loop 'for 'line '= (list 'read filevar 'nil ':eof)
          'until (list 'eq 'line ':eof)
          'do
          ; (list 'print 'line)
          (list 'setq listname (list 'append listname (list 'elt 'line nthmember))))))

当我运行命令时:

(readextracttolist xx "syminput_0.txt" 0 usedmollist)

我得到:

The value
  H2O
is not of type
  LIST

期待:

list USEDMOLLIST:

(H2O O2)
list macros lisp
1个回答
0
投票

主要问题是您尝试将单个元素而不是列表附加到现有列表,这在宏扩展宏后更容易看到:

(macroexpand '(readextracttolist xx "syminput_0.txt" 0 usedmollist))
(PROGN
 (DEFPARAMETER XX (OPEN "syminput_0.txt"))
 (LOOP FOR LINE = (READ XX NIL :EOF)
       UNTIL (EQ LINE :EOF)
       DO (SETQ USEDMOLLIST (APPEND USEDMOLLIST (ELT LINE 0)))))

此外,通过使用

backquote
语法可以使宏更具可读性,其中仅替换以
,
为前缀的符号。
progn
defparameter
也可以替换为
let
:

(defmacro readextracttolist (filevar filename nthmember listname)
  `(let ((,filevar (open ,filename)))
     (loop for line = (read ,filevar nil :eof)
       until (eq line :eof) do
       (print line)
       (setq ,listname (append ,listname (list (nth ,nthmember line)))))))

另外:这里可能不需要宏,因为函数可以完成这项工作(例如,通过返回要附加到现有列表的列表)。

© www.soinside.com 2019 - 2024. All rights reserved.