代码之家  ›  专栏  ›  技术社区  ›  Thunfische

将列表写入Lisp中的文件

  •  1
  • Thunfische  · 技术社区  · 7 年前
    (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 回复  |  直到 7 年前
        1
  •  4
  •   sds Niraj Rajbhandari    7 年前

    误差

    此错误记录在 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 .