News for hackers. Stuff that matters.
Re:Advantages of Tcl over Lisp (2005) by TeMPOraL on Monday October 30, 2017 @05:49AM (#15583913)
Serializing code like this is a bad example, because you need to introduce eval into the loop, which is another step entirely from printing and reading objects. Consider this example, from REPL interaction:

  CL-USER> (with-open-file (f "/tmp/makapaka"
                            :direction :output
                            :if-exists :supersede)
             (pprint '(a potentially (complex data structure)
                       mixing lists #(and vectors) 2/3
                       #C(2 5) and stuffs) f))
  ; No value

  CL-USER> (with-open-file (f "/tmp/makapaka")
             (read f))
  (A POTENTIALLY (COMPLEX DATA STRUCTURE) MIXING LISTS #(AND VECTORS) 2/3 #C(2 5)
   AND STUFFS)
In this example, I printed and read back a list containing symbols, lists, vectors, rationals and complex numbers.

Basically: the reader converts strings to Lisp objects[0]. The printer converts Lisp objects into strings. When we say that an object has a "readable representation", it means that if you feed the result of the printer into reader, you get the same object back.

The evaluator (which I didn't use here, but OP did) evaluates Lisp objects (not strings!), and can e.g. introduce a new function to the environment when evaluating a defun form, i.e. a list of form (defun name (args...) "docstring" code). It is not needed (in fact, it is discouraged[1]) when all you care about is writing and reading back Lisp objects.

--

[0] - Note it's the same reader that actually reads your code when you compile/load file or use a REPL.

[1] - The usual eval-on-untrusted-data code execution vulnerability. Note that since the reader is mostly used to process code, by default it allows you to use the #. read-time-value reader macro. If you READ a string like: "(1 2 #.(* 2 2))", you'll get a Lisp list (1 2 4), since #. basically means "pipe the next s-expression to eval, and return that". When you use reader/printer for serialization/deserialization, you usually want to disable #. for those invocation of read function, by setting

  *READ-EVAL*
variable to NIL.

There are no comments on this comment yet.