On Thu, Sep 8, 2011 at 5:16 PM, Tassilo Horn <tass...@member.fsf.org> wrote: > Hi all, > > I've just read Alan Malloy's excellent clojure persistence article at > > http://amalloy.hubpages.com/hub/Dont-use-XML-JSON-for-Clojure-only-persistence-messaging > > Then I wanted to add a feature for persisting and reloading clojure data > that also contains vertices and edges of some java graph datastructure. > In contrast to his java.util.Date example, those cannot be simply > created but have to be retrieved in the context of the graph that holds > the vertex or edge in question. > > All vertices and all edges have a numeric and unique id in their graph, > and a graph itself has a unique graph id (some string). A vertex can be > retrieved by id using (vertex mygraph id), and it's likewise for edges > (edge mygraph id). > > So my plan was to serialize vertices and edges as calls to those > functions where the graph is looked up in a hash-map that has to be > bound dynamically when reading the data back. That's what I came up > with: > > --8<---------------cut here---------------start------------->8--- > (def ^:dynamic > *serialization-bindings* nil) > > (defmethod print-dup Vertex [v out] > (.write out > (str "#=" > `(vertex (*serialization-bindings* ~(id (graph v))) ~(id v))))) > > (defmethod print-dup Edge [e out] > (.write out > (str "#=" > `(edge (*serialization-bindings* ~(id (graph e))) ~(id e))))) > > (defn tg-pr [x] > (binding [*print-dup* true] > (pr-str x))) > --8<---------------cut here---------------end--------------->8--- > > Testing that (rg is a memoized fn that returns just some sample graph), > I get > > ==> (tg-pr [1 2 3 (vertex (rg) 1) 4]) > "[1 2 3 #=(de.uni-koblenz.funtg.core/vertex > (de.uni-koblenz.funtg.core/*serialization-bindings* > \"c06de1c7-f4ec0906-21cfbc86-28c31aa1\") 1) > 4]" > > Looks good, I'd say. So my reloading function only needs to bind > *serialization-bindings* to a map from graph id to graph, and it should > work. > > --8<---------------cut here---------------start------------->8--- > (defn tg-read [str & gs] > (binding [*serialization-bindings* (into {} (map (fn [g] [(id g) g]) > gs)) > *print-dup* true] > (binding [*print-dup* false] ;; For debugging... > (println *serialization-bindings*)) > (read-string str))) > --8<---------------cut here---------------end--------------->8--- > > However, using that, I get an exception. > > de.uni-koblenz.funtg.test.core> (tg-read (tg-pr [1 2 3 (vertex (rg) 1) 4]) > (rg)) > {c06de1c7-f4ec0906-21cfbc86-28c31aa1 #<RouteMapImpl > de.uni_koblenz.jgralabtest.schemas.greqltestschema.impl.std.RouteMapImpl@5203e0c6>} > ; Evaluation aborted. > No implementation of method: :vertex of protocol: > #'de.uni-koblenz.funtg.core/IDOps found for class: clojure.lang.PersistentList
I haven't tried all the above, but I had a couple thoughts that might help: First, inside #=(), arguments aren't evaluated. They act as if quoted: #=(+ 1 (+ 2 4)) ; ClassCastException clojure.lang.PersistentList cannot be cast to java.lang.Number clojure.lang.Numbers.add (Numbers.java:126) The list (+ 2 4) is passed as a list to the outer +, which fails because it's expecting a number not a list. So one alternative would be: #=(+ 1 #=(+ 2 4)) ;=> 7 But please consider another alternative: (+ 1 (+ 2 4)) ;=> 7 That is, if you're going to be evaluating a large amount of code while reading your data back into memory, why not just go ahead and eval it instead of just reading it? (read-string "#=(+ 1 #=(+ 2 4))") vs. (eval (read-string "(+ 1 (+ 2 4))")) --Chouser -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en