Fork me on GitHub
#code-reviews
<
2023-02-21
>
stopa17:02:45

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?

seancorfield18:02:44

No need for doall with reduce but otherwise that seems reasonable.

❤️ 4
stopa18:02:25

Thanks Sean! Removed the doall :right-facing_fist::left-facing_fist: