我想将文本文件中的列表添加到lisp并将其绑定到某个变量。 例如 Mylist.txt包含: ((1 2 3 4) (5 6 7 8) (9 10 11 12) (13 14 15 16) ) 我想从这个文件中读取并将此列表设置为某个变量mylist。
(defun readfile (fileName) (let ((in (open fileName :if-does-not-exist nil)))
(when in
(loop for line = (read in nil)
while line do (print line))
(close in)
)
) )
(setf myList (readfile "list.txt"))
输出应该是(myList应该有界): ((1 2 3 4) (5 6 7 8) (9 10 11 12) (13 14 15 16) )
我已经看到了关于此问题的大部分关于stackflow的答案,但是非他们工作的例子我尝试逐行阅读并使用了收集但是这似乎没有给我正确答案,因为它收集了整行并将其视为列表项。
答案 0 :(得分:0)
到目前为止,您正在读取文件并将其打印到标准输出((print line)
中的READFILE
语句)。相反,您想收集输入。
(defun read-file (file-name)
(let ((*read-eval* nil))
(with-open-file (in file-name)
(loop for x = #1=(read-line in nil :eof) then #1#
until (eq x :eof)
collect (read-from-string x)))))
行由行:
1.请将CL约定用于名称。
2.在read macros出现时,从字符串/文件中读取是危险的。将*READ-EVAL*
设置为NIL
会阻止其执行。
我们需要做的阅读很简单。使用WITH-OPEN-FILE
提供了一个简单而安全的界面(例如,如果引发条件(异常),它将正确关闭文件)。 IN
是与文件关联的输入流的名称。
4.在每次迭代的LOOP
中读取一行。这里我假设每一行都是一个合适的Lisp表达式(例如,数字或列表)。如果您的表达式跨越多行,则需要更改。 #1=
可让您记住其后的表单,并#1#
插入该表单。这用于避免重复初始和然后语句的(READ-LINE ...)
形式。如果到达文件末尾,则READ-LINE
不会引发错误,而是返回:EOF
。
5.直到达到文件结尾...
6.读取(从字符串转换为Lisp数据)并收集从文件读取的行。
此函数返回(读入Lisp数据)文件行的列表。例如,如果“text.txt”包含
((1 2 3) (4 5 6))
(a b c)
(:f :g :h)
“test.txt”的READ-FILE
将导致:
CL-USER> (read-file "test.txt")
(((1 2 3) (4 5 6)) (A B C) (:F :G :H))
最后,除非使用SETF
或MY-LIST
定义DEFVAR
(在这种情况下应将其命名为DEFPARAMETER
),否则请勿使用*MY-LIST*
是使用LET
在本地定义的。