在Lisp中将列表写入文件

时间:2019-01-01 18:28:46

标签: io lisp common-lisp

(defun foo (mylist)
  (with-open-file (str "out.txt"
                       :direction :output
                       :if-exists :append
                       :if-does-not-exist :create)
    (if mylist
        (progn
          (format str (car mylist))
          (foo (cdr mylist))))))

我有两个问题。首先,我无法使用此表达式(format str (car mylist))编写列表的元素,其次,它还会产生另一个错误,如下所示。

             already points to file
             "out.txt", opening the file again for :OUTPUT may produce
             unexpected results
             Open the file anyway

1 个答案:

答案 0 :(得分:4)

错误

此错误记录在the manual中。 您正在递归调用foo,每次调用都会再次打开文件。 这可能会带来非常糟糕的后果。

重新打开

您可以通过将递归调用移到with-open-file之外来解决此问题:

(defun write-list-to-file-reopen (mylist destination)
  (when mylist
    (with-open-file (str destination
                         :direction :output
                         :if-exists :append
                         :if-does-not-exist :create)
      (prin1 (pop mylist) str)
      (terpri str))
    (write-list-to-file-reopen mylist)))

但这效率很低,因为open是相对昂贵的操作。

更好的解决方案是进行迭代

(defun write-list-to-file-iterate (mylist destination)
  (with-open-file (str destination
                       :direction :output
                       :if-exists :append
                       :if-does-not-exist :create)
    (dolist (el mylist)
      (format str "~S~%" el))))

或者,如果需要使用递归,

(defun write-list-to-file-recursion (mylist destination)
  (with-open-file (str destination
                       :direction :output
                       :if-exists :append
                       :if-does-not-exist :create)
    (labels ((write-list (list)
               (when list
                 (prin1 (pop list) str)
                 (terpri str)
                 (write-list list))))
      (write-list mylist))))

格式

功能format相对来说 重量很重并且打算用于交互式漂亮的打印, 宁愿使用write之类的简单函数。

您的问题是因为您的(format str x)应该是(format str "~S~%" x): 您忘记了format string