Skip to content

Instantly share code, notes, and snippets.

@senior
Last active December 13, 2015 22:18
Show Gist options
  • Select an option

  • Save senior/4983149 to your computer and use it in GitHub Desktop.

Select an option

Save senior/4983149 to your computer and use it in GitHub Desktop.
gmatche from Practical core.logic - ClojureWest 2012
(defn lvarify
"Using _ for don't care types of values works fine when using the matche and conde
macros directly, but not as well when other macros wrap it. This will walk a list,
looking for _ values and swapping them for new logic variables. This translates into
the same don't care values when using conde/matche directly."
[sym-list]
(vec (map #(if (= % '_)
`(lvar)
%)
sym-list)))
(defn qmark-sym? [x]
(= \? (first (name x))))
(defn- freshen
"Searches vectors of the form [x y z] looking for ?x types of variables"
[spo-vecs]
(vec (filter qmark-sym? (set (apply concat spo-vecs)))))
(defmacro gmatche
"Matches one or more resources in a graph. where all of the spo-vecs are matched in the graph.
spo-vecs is a triple of the form [x y z]. Values of _ will not matter and values of ?sym will
have a new logic var created (scoped at the gmatche level over multiple tiple-matches). An example
triple pattern [:a _ ?f] [?f _ :a] would find values for ?f where :a is subject, ?f is object and
?f is subject and :a is object."
[graph & spo-vecs]
(let [graph-sym (gensym "graph")]
`(let [~graph-sym ~graph]
(fresh ~(freshen spo-vecs)
~@(map (fn [x#]
`(membero ~(lvarify x#) ~graph-sym)) spo-vecs)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment