Appending Text to a File

The Nyquist/XLisp OPEN function has the habit to overwrite an existing text file without warning. Here is way how the XLisp OPEN function can be used to to append text to a file instead of overwriting:

(defun append-to-file (filename &rest strings)
  (when strings
    (let (stream buffer)
      ;; first try to read the file into a buffer
      (unwind-protect
        (when (setq stream (open filename :direction :input))
          ;; if the file could be opened for reading
          (do ((line (read-line stream)
                     (read-line stream)))
              ((null line))
          (setq buffer (cons line buffer))))
        (when stream
          ;; if the file was opened, close it
          (close stream)
          (setq stream nil)))
      ;; write the buffer and append the new text
      (unwind-protect
        (when (setq stream (open filename :direction :output))
          ;; if the file could be opened for writing
          (when (not (endp buffer))
            ;; if there is text in the buffer
            (setq buffer (reverse buffer))
            (dolist (line buffer)
              (format stream "~a~%" line)))
          ;; write the new text
          (dolist (line strings)
            (format stream "~a~%" line)))
        (when stream
          ;; if the file was opened, close it
          (close stream)
          filename)))))

If no file exists where the text could be appended, then a new file will be created. The file gets automatically closed after the text has been written.

  • edgar

That’s a similar principal to something I posted elsewhere on the forum, but I notice that you use a different test for the end of the file.
In my code I have:

(do ((nextline (read-line fp)(setq nextline (read-line fp)))(readtest ""))
        ((not nextline) readtest)
        (setq readtest (strcat readtest nextline "n")))

whereas you have:

(do ((line (read-line stream)
                     (read-line stream)))
              ((null line))
          (setq buffer (cons line buffer)))

Do the tests (null line) and (not nextline) do the same thing or is there a difference?

There is only an “esoteric” difference: NULL means “object with no contents” while NOT means “the opposite of”. In practice both functions test if a Lisp object evaluates to NIL. In XLisp, NOT is defined as an alias to NULL in “lib-src/libnyquist/nyquist/xlisp/xlinit.c” around line 106:

setfunction(xlenter("NOT"),getfunction(xlenter("NULL")));

So we can tell for sure that in XLisp both functions behave exactly the same.

  • edgar