public
Created — forked from lynaghk/gist:4116442

Possible syntaxes for flexible unifier w/ multi-lvar constraints

  • Download Gist
gistfile1.clj
Clojure
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
;;Support for simple constraints on lvars during unification was added in 76fd4d7c:
;;
;; https://github.com/clojure/core.logic/commit/76fd4d7c155161d74ad5cd8d87955148eece1fe0
;;
;;but these constraints apply to a single lvar only.
;;The unifier could support more general constraints if it accepted an explicit predicate function.
 
;;For instance, given this `data-numeric?` predicate and `spec` data:
 
(defn data-numeric? [data dimension]
(number? (-> data first dimension)))
 
(def spec {:data (repeatedly 10 #(hash-map :val (rand) :cat (rand-nth [:a :b :c])))
:mapping {:y :val}})
 
;;I'd like a unifier call that has the same semantics as:
 
(run* [q]
(fresh [data dim]
(== spec {:data data :mapping {:y dim}})
(project [data dim]
(== true (data-numeric? data dim)))
(== q :success)))
 
;;A concise syntax is
 
(unifier1 spec
'{:data ?data :mapping {:y ?dim}}
'(data-numeric? ?data ?dim))
 
;;but that would require `unifier1` to
;; + prep all of its arguments together
;; + treat its third argument (or last, if more than 3 args) specially
;; + prep, project, and eval the predicate form, which feels gross.
 
;;We can avoid the last-argument issue via a dynamic var:
 
(binding [*unifier-constraints* '(data-numeric? ?data ?dim)]
(unifier2 spec))
 
;;This maintains backwards compatibilty at the expense of being klunky (and suffers from the same prep+project+eval issue).
 
;;A more programmatically flexible syntax:
 
(unifier3 '[spec {:data ?data :mapping {:y ?dim}}
:where
[data-numeric? ?data ?dim]])
 
;;where everything before the `:where` is something to unify and everything after is a tuple of the form [predicate & lvar-arguments].
;;This syntax could be used with the existing unifier since the single-arity implementation is currently undefined.
;;This syntax is my preference thus far.
 
 
;;In any of these syntaxes, I'm not sure if we can/want to support anonymous functions, or if in that case the user should just ball up and write a full run* form.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.