On Thu, Sep 8, 2011 at 5:16 PM, Tassilo Horn <[email protected]> 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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en