I usually just give every ENTITY in my system a primary id and structure everything in a nested map.
{:people {1 {:id 1 :type :student :name "Ben" :taking-classes #{1 2}} 2 ...} :classes {1 {:id 1 :name "Clojure 101"} 2 ...}} This basically looks like a database table. You can also go with something a little more flat. {1 {:type :student, :name "Ben" :taking-classes #{3}} 3 {:type :class, :name "Clojure 101"}} Usually needs some form of indexing otherwise you are taking some performance hits if you have alot of entities in your system. You dont want to (->> (vals @data) (filter #(= :class (:type %))) every time you want to list all :classes. Nothing fancy but it is simple. On Thursday, July 10, 2014 10:26:33 AM UTC+2, Bertrand Dechoux wrote: > > Hi, > > I have various general questions about how one can perform simple and > flexible graph query/update. > > If we start by a structure being nested maps then I know about > get-in/update-in/assoc-in. The common point about these functions is that > they all take a path to where the data is in the superstructure and that > this path is only a sequence of keys, which may or not be symbols. > > 1) What happens when one layer of this superstructure is not a map but a > sequence? For the sake of the argument, we can keep the discussion simple > by only arguing about the vector case. > > Typically instead of > { :key1 { :key2 val }} > > we now have > { :key1 [{ :key2 val }]} > > Of course, one can perform get/update/assoc using map/reduce. However, it > means that the code using this superstructure is taking a hit on > complexity/maintenance each time a non-map layer must be crossed. Of > course, the simplicity/beauty of the current implementation is that a path > can point to at most one target substructure/value. Is there a way to do > something similar with a more general definition of a path? One would > assume that it is something that might be handled by xml/html modification > libraries (think xpath or css selector) but this problem is more general > and not domain specific. Is there a clean library that handle that case > without being tied to html/xml? > > 2) How to deal with more general superstructure like a graph? > > One could build an immutable graph but I don't believe it is something > that can be done by nesting immutable maps and vectors. One solution to > deal with 'entity'--'entity' relationships is for one of the member to own > only an identifier to get the other member from another reference structure. > > (from the basic OM tutorial:) > > {:people > [{:type :student :first "Ben" :last "Bitdiddle"} > {:type :professor :first "Gerald" :last "Sussman" :classes [:6001 > :6946]}] > :classes > {:6001 "The Structure and Interpretation of Computer Programs" > :6946 "The Structure and Interpretation of Classical Mechanics" > :1806 "Linear Algebra"}} > > > It is, of course, again, manually possible to get/update/assoc using > map/reduce. But then, again, this is the same problematic as with the > first question : each time a relation needs to be crossed, the code using > this superstructure is taking a hit on complexity/maintenance. How do you > usually deal with this problematic? > > For both question 1) and 2), a more appropriate data structure might be > the answer like a graph/semantic-like store (Datomic or something else). > The questions are about intermediary solutions which would be less heavier. > > 3) How does Demeter lives with graph traversal? > > This law is often heard in the OOP world but it is a bit more general than > that. When a long path on a superstructure is specified then if one > intermediary layer is introduced later, all hardcoded paths will be broken > ie in multiple locations in the code base. One would like to store local > structure knowledge in a single place. How do you usually deal with this > problematic? > > I have yet to take a serious look at lenses and their composition, they > are probably an element of answer, but they are more often seen in more > statically typed langage. > > Thanks for any feedback. > > Bertrand > -- 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 --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.