Christopher Small, Your suggestion to look into Datomic definitely turned up a new idea. I went through the Datalog tutorial at http://www.learndatalogtoday.org (which is excellent, by the way), and noticed that the attribute names in the datoms are a lot like the port labels in port graphs. A port label is essentially an attribute key whose value is the edges incident to it. And when you chain data patterns in Datalog queries, that's a lot like navigating through a graph.
The new, hopefully simple, easy-to-use, and not error-prone idea is to use the clojure.lang.IPersistentMap interface to query and update graphs. Nodes, edge, attribute names, port labels, and a few "reserved keywords" like :adj-nodes and :edge, could navigate the graph as if it were an ordinary nested map with get-in, assoc-in, and the like, without ever needing to wrap anything inside a record to tell what it is. Here are some sample queries and what they could return: (get-in g [node port-label :adj-nodes]) a coll of all the nodes with an edge to [node port-label] (get-in g [node port-label :adj-node]) one node with an edge to [node port-label], or nil (get-in g [node port-label]) true or false, according to whether node has a port named port-label (get-in g [node k]) value of node's attr k (get-in g [edge k]) value of edge's attr k (get g node-or-edge) the entire map of attrs associated with node-or-edge, or nil if it does not exist (get-in g [node k1 k2 k3]) treat node's attrs as a nested map (get-in [node port-label :edges]) a coll of all the edges that link to [node port-label] (get-in [node port-label :edge]) a single edge that links to port-label, or nil (get-in [node port-label1 port-label2]) coll of all nodes that link to [node port-label1] from a port named port-label2 And here are some function calls that would return a modified graph: (assoc-in g [node k] v) sets node attr k to v (assoc-in g [edge k] v) sets edge attr k to v (and similarly for multiple keys) (assoc-in g [node1 port-label1 port-label2 node2] :edge) makes an edge between [node1 port-label1] and [node2 port-label2] (assoc-in g [node1 port-label1 port-label2 :edge k] v) sets value of edge attr k to v I haven't yet thought this through completely, and I suspect that some parts are still error-prone. For example, notice in the last function call that it's not clear whether you should include node2. The approach might be "too cute"—that is, brittle because it tries to impose one kind of structure (nested maps) onto one that isn't fully isomorphic (graphs). But I like the basic idea of having a "little language" for designating whatever you want, and the little language is nothing but a sequence that tells how to navigate through the graph to find (or make) what you're interested in. This would solve the fundamental problem of how to designate an edge without imposing type restrictions. For each connection point, you just have a sequence that describes a path to that point. If the sequence ends on a port label, the connection point is a port. If it ends on :edge, the connection point is an edge. So, instead of type restrictions, there are just a few reserved words in the tiny DSL for navigating the graph. This hopefully makes simple editing and querying of port graphs easy, but it does not even try to solve the problem of conveniently entering a graph. I figure that a "shorthand", i.e. a separate tiny DSL, is the solution for that. I found with my current implementation of port graphs that it really helped to use a custom shorthand for each specific type of graph. For example, there's a obvious and very nice shorthand for specifying graphs that represent mathematical expressions, but it's terrible for graphs of social networks. Graphs of social networks, though, can be conveniently described by their own custom sexprs. I figure that implementing it will force me to think this idea through the rest of the way. Here goes… -- Ben Kovitz http://pages.iu.edu/~bkovitz/ -- 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.