Search code examples
lispcommon-lisps-expression

symbolic expression stream I/O


In Common Lisp, how can one read & write symbolic expressions from/to streams? For example, I might want to write an anonymous function to file and then read and funcall it:

;;; sexp-io.lisp
;;; Try writing a sexp to file and reading it back in

(with-open-file (file "~/Documents/Lisp/Concurrency/sexp.lisp"
                  :direction :output :if-exists :supersede)
  (print #'(lambda () (+ 1 1)) file))

(with-open-file (file "~/Documents/Lisp/Concurrency/sexp.lisp"
                  :direction :input)
  (read file))

However, that code results in dubious output

 #<Anonymous Function #x3020018F950F>

which does result in an error when I try reading it back in:

> Error: Reader error on #<BASIC-FILE-CHARACTER-INPUT-STREAM ("/Users/frank/Documents/Lisp/Concurrency/sexp.lisp"/7 UTF-8) #x3020018F559D>, near position 3, within "
>        #<Anonymous ":
>        "#<" encountered.
> While executing: CCL::SIGNAL-READER-ERROR, in process Listener(4).

Solution

  • You are doing TRT, except for #' which turns the list (lambda () (+ 1 1)) into a function object. Just replace the sharp-quote (which is read as function) with a simple quote (which is read as quote) and it should work.

    Another change you might want to make is replacing print with write with argument :readably t:

    (write my-object :stream out :readably t)
    

    The benefit of :readably is that it fails if it cannot write in a way that will preserve print-read consistency.