我有一个读取文件的宏 其格式如下: (水 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)
主要问题是您尝试将单个元素而不是列表附加到现有列表,这在宏扩展宏后更容易看到:
(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)))))))
另外:这里可能不需要宏,因为函数可以完成这项工作(例如,通过返回要附加到现有列表的列表)。