Problems

  1. It's very easy to accidentally print invalid EDN
    1. eg when doing host interop
    2. Workaround: (assert (= (clojure.edn/read-string (pr-str value)) value))
  2. There is no standard in-memory representation for tagged literals
    1. This is a problem for tools that want to analyze code
    2. Workaround: (defrecord TaggedLiteral [tag value]), *default-data-reader-fn*
      1. Fails when tools want to collaborate: differing representations
    3. RESOLVED! in clojure 1.7
  3. extending print-method is a bad model
    1. Exposes mutable printer
    2. Requires each tagged-literal provider to implement the same printing logic
    3. Allows printing of unreadable forms

Potential Solution

  1. (defrecord TaggedLiteral [tag value])
    1. Has a print-method which does the #tagged/literal "thing"
  2. (defprotocol ILiteral (-literal [this]))
    1. Converts an object into a valid EDN structure
  3. Add pr, prn, pr-str, and prn-str to clojure.edn
    1. Implements closed set of print methods for each EDN type
    2. Calls -literal on every object recursively
    3. Throws if any object isn't one of the EDN types

Questions

Should ->EDN conversion be shallow or deep? Points for each.

My vote: Shallow, since almost every use of this protocol will immediately result in a composed (and often early-terminated) traversal.

An Implementation

See https://github.com/brandonbloom/fipp/blob/7a62966e1c0e84df1b9f37896626393aa6721d43/src/fipp/visit.clj

and https://github.com/brandonbloom/fipp/blob/8f002c6e5db58b18cefd807dd602390249286e5b/src/fipp/ednize.clj