Запись списка в файл в lisp - PullRequest
0 голосов
/ 01 января 2019
(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 голосов
/ 01 января 2019

Ошибка

Эта ошибка описана в руководстве .Вы вызываете 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): вы забыли строку формата .

...