I have a list of named ::patterns -- think of them as the [?e ?a ?v] patterns in the datalog :where
I want to make sure that every pattern is "joinable". This means there is at least one variable in subseuent patterns, which existed in the previous patterns.
So this is joinable:
(ensure-joinable
(s/conform ::patterns '[[:ea ?e ?a ?v]
[:ea ?e ?b ?c]]))
; ?e connects the second pattern with the first
But this would throw:
(try (ensure-joinable
(s/conform ::patterns '[[:ea ?e ?a ?v]
[:ea ?c ?b ?c]]))
(catch clojure.lang.ExceptionInfo e
(ex-data e)))
; no way to connect the second pattern
Here's my implementation:
(defn ensure-joinable [[first-pat & rest-pats :as named-pats]]
(doall (reduce
(fn [seen named-pat]
(let [vset (named-variables named-pat)
connected? (seq (cset/intersection seen vset))]
(if-not connected?
(throw (ex-info "Pattern is not joinable" {:patterns named-pats
:bad named-pat}))
(cset/union seen vset))))
(named-variables first-pat)
rest-pats)))
I'm using reduce because I want to be a bit more friendly in the error message. Would you do it differently?No need for doall with reduce but otherwise that seems reasonable.
Thanks Sean! Removed the doall 🤜🤛