News for hackers. Stuff that matters.
Re:Advantages of Tcl over Lisp (2005) by emidln on Sunday October 29, 2017 @11:05PM (#15582877)
> You can write a TCL list to a file? You mean a TCL string to a file? Lisp can just write strings to files too.

To expand upon this, Lisp can write its lists to files (and most other things out of the box) which it can then read back from files and then eval. This is what Lisps mean by a printable/readable object.

In Clojure:

    (spit "foo.clj" '(defn foo [] "CONGRATS! YOU CALLED FOO!!!"))
    (load-file "foo.clj")
    (foo) ; => "CONGRATS! YOU CALLED FOO!!!"
In Common Lisp:

    (with-open-file (f "foo.lisp" :direction :output)
           (pprint 
             '(defun foo () 
                "CONGRATS! YOU CALLED FOO!!!!") f))
    (with-open-file (f "foo.lisp" :direction :input)
           (eval (read f)))
    (foo) ; => "CONGRATS! YOU CALLED FOO!!!!"
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.