Clisp从文件中读取列表并将其展平,但无法正常工作,无法将lst识别为列表

问题描述

(defun read-file-list (infile)
  (with-open-file (instream infile :direction :input :if-does-not-exist nil)
   (when instream 
     (let ((list (make-list (file-length instream))))
       (read-sequence list instream)
       list))))


(setq lst (read-file-list "/home/Desktop/nested_list.txt"))

(flatten-list lst )

(print lst)

;(1 2 3 (4 5 (12 11 9 6) 4 8 (77 53(47)) (12 15 18)) 
; file has got this line

解决方法

READ-SEQUENCE从文件中读取字符。计算file-length并调用read-sequence时,您要做的就是读取平面列表中的所有字符。即,您的示例中的lst是以下列表:

(#\( #\1 #\  #\2 #\  #\3 #\  #\( #\4 #\  #\5 #\  #\( #\1 #\2 #\  #\1 #\1 #\
 #\9 #\  #\6 #\) #\  #\4 #\  #\8 #\  #\( #\7 #\7 #\  #\5 #\3 #\( #\4 #\7 #\)
 #\) #\  #\( #\1 #\2 #\  #\1 #\5 #\  #\1 #\8 #\) #\) #\Newline)

您可以看到此列表中的所有元素都是字符,它们用#\...语法表示。例如,第一项描述如下(通过SBCL测试,实际输出可能会因您的实现而异):

* (describe (first lst))
#\(
[standard-char]

Char-code: 40
Char-name: LEFT_PARENTHESIS
; No value

(带有打开文件(流“ /tmp/file-list.txt”)) (读取(make-concatenated-stream(make-string-input-stream“(”) 流 (make-string-input-stream“)”))))) 您要做的是在该文件上调用READ

* (with-open-file (in "/tmp/file-list.txt")
    (read in))
; Evaluation aborted on #<END-OF-FILE {1013420B23}>.

似乎您的输入文件也缺少右括号。解决该问题后,您将:

* (with-open-file (in "/tmp/file-list.txt")
    (read in))
(1 2 3 (4 5 (12 11 9 6) 4 8 (77 53 (47)) (12 15 18)))

此处读取的值是数字列表和嵌套列表。

* (describe (first *))
1
[fixnum]
; No value

----编辑

您的flatten-list函数似乎正常工作,我的意思是您的输入列表在另一个文件中,并且您需要通过调用read使用标准的Lisp阅读器来提取数据: / p>

* (with-open-file (in "/tmp/file-list.txt")
    (flatten-list (read in)))

(1 2 3 4 5 12 11 9 6 4 8 77 53 47 12 15 18)

-编辑2

如果您的文件包含列表元素,例如:

1 2 3 (4 5 (12 11 9 6) 4 8 (77 53(47)) (12 15 18))

然后您可以编写一个循环,如下所示:

(loop 
  for form = (read in nil in)
  until (eq form in)
  collect form)

或者,您可以使用串联流:

USER> (with-input-from-string (open "(")
        (with-input-from-string (close ")")
          (with-open-file (file "/tmp/file-list.txt")
            (read (make-concatenated-stream open file close)))))
(1 2 3 (4 5 (12 11 9 6) 4 8 (77 53 (47)) (12 15 18)))

或等效地:

(with-open-file (stream "/tmp/file-list.txt")
  (read (make-concatenated-stream (make-string-input-stream "(")
                                  stream
                                  (make-string-input-stream ")"))))