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
  [Thrown class java.lang.IllegalArgumentException]

Restarts:
 0: [QUIT] Quit to the SLIME top level

Backtrace:
  0: clojure.core$_cache_protocol_fn.invoke(core_deftype.clj:495)
  1: 
de.uni_koblenz.funtg.core$eval6716$fn__6717$G__6705__6724.invoke(core.clj:381)
  2: clojure.lang.Var.invoke(Var.java:405)
  3: clojure.lang.AFn.applyToHelper(AFn.java:163)
  4: clojure.lang.Var.applyTo(Var.java:518)
  5: clojure.lang.LispReader$EvalReader.invoke(LispReader.java:1041)
  6: clojure.lang.LispReader$DispatchReader.invoke(LispReader.java:618)
  7: clojure.lang.LispReader.readDelimitedList(LispReader.java:1126)
  8: clojure.lang.LispReader$VectorReader.invoke(LispReader.java:1061)
  9: clojure.lang.LispReader.read(LispReader.java:180)
 10: clojure.lang.RT.readString(RT.java:1681)
 11: clojure.core$read_string.invoke(core.clj:3359)
 12: de.uni_koblenz.funtg.core$tg_read.doInvoke(core.clj:1041)

The printed *serialization-bindings* map looks correct.  But the
exception message indicates that the `vertex' function was called with a
list as first parameter.  That would mean that in
*serialization-bindings* the graph id was mapped to some list?!?

What's wrong here?  (Clojure 1.3 if that matters...)

Thanks for any pointers,
Tassilo

-- 
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

Reply via email to