I'm trying to use *print-dup* to allow writing clojure data to a file and then read it back, however, I'm getting problems even with this simple case. Is there something I am doing wrong? What do I need to do to get this to work?
Clojure 1.3.0-alpha3-SNAPSHOT
user=> (defrecord TreeNode [val left right]) ;;create the record
user.TreeNode
user=> (TreeNode. 5 nil nil)
#:user.TreeNode{:val 5, :left nil, :right nil} ;; it works just fine
user=> (binding [*print-dup* true] (prn (TreeNode. 5 nil nil))) ;; use *print-dup* to support reading in and preserving type
#=(user.TreeNode/create {:val #=(java.lang.Long. "5"), :left nil, :right nil}) ;; this is the form we need to copy paste
nil
user=> #=(user.TreeNode/create {:val #=(java.lang.Long. "5"), :left nil, :right nil}) ;;trying to copy and paste
IllegalArgumentException No matching method found: create
clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:50) ;;we have an error
user=>
Records don't print in an eval-able form. We added our own defrecord2 that includes support for creating constructor functions and print/pprint support to print them using the constructor function (which can be eval'ed back into the original record). This is doc'ed more here and here and the code is here.
I asked Rich Hickey about this issue at the Clojure Conj conference in Oct. 2010 and he said constructor functions and reader support for records are planned for the future.
As an update, as of alpha8, in the simple case, *print-dup* with records now works.
user=> (defrecord TreeNode [val left right])
user.TreeNode
user=> (TreeNode. 5 nil nil)
#user.TreeNode{:val 5, :left nil, :right nil}
user=> (binding [*print-dup* true] (prn (TreeNode. 5 nil nil)))
#user.TreeNode[5, nil, nil]
nil
user=> #user.TreeNode[5, nil, nil]
#user.TreeNode{:val 5, :left nil, :right nil}
user=>
Work around in 1.2:
(defn- extend-print-dup [record-class]
(defmethod print-dup record-class [o w]
(.write w "#=(")
(.write w (.getName ^Class (class o)))
(.write w ". ")
(dorun (map (fn [a] (print-dup a w) (.write w " ")) (vals o)))
(.write w ")")))
(defrecord Hl7Field [protospec segname fname pos hl7type values])
(extend-print-dup Hl7Field)
=> (def a (Hl7Field. "p" "PV1" "toto" 0 "ST" ["c" "d"]))
=> (binding [*print-dup* true] (prn a))
#=(higiebus.bus.protocol.hl7.Hl7Field. "p" "PV1" "toto" 0 "ST" ["c" "d"] )
=> #=(higiebus.bus.protocol.hl7.Hl7Field. "p" "PV1" "toto" 0 "ST" ["c" "d"] )
{:protospec "p", :segname "PV1", :fname "toto", :pos 0, :hl7type "ST", :values ["c" "d"]}
You could wrap the call to extend-print-dup in a custom defrecord macro.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With