As we start adding more constraints it's becoming clear we really want to have to specify less boiler plate. Instead of:
(defn -treec
([x fc cform] (-treec x fc cform nil))
([x fc cform _id]
(reify
clojure.lang.IFn
(invoke [this a]
(let [x (walk a x)]
(if (tree-term? x)
((composeg
(constrain-tree x
(fn [t a] ((treec t fc cform) a)))
(remcg this)) a)
((composeg
(fc x)
(remcg this)) a))))
IConstraintId
(id [this] _id)
IWithConstraintId
(with-id [this _id]
(-treec x fc cform _id))
IConstraintOp
(rator [_] `treec)
(rands [_] [x])
IReifiableConstraint
(reifyc [_ v r a]
(let [x (walk* r x)]
`(treec ~x ~cform)))
IRelevant
(-relevant? [_ a] true)
IRunnable
(runnable? [_ a]
(not (lvar? (walk a x))))
IConstraintWatchedStores
(watched-stores [this] #{::subst}))))
(defn treec [x fc cform]
(cgoal (-treec x fc cform)))
We should be able to write just:
(defc treec [x fc cform]
clojure.lang.IFn
(invoke [this a]
(let [x (walk a x)]
(if (tree-term? x)
((composeg
(constrain-tree x
(fn [t a] ((treec t fc cform) a)))
(remcg this)) a)
((composeg
(fc x)
(remcg this)) a))))
IConstraintRands
(rands [_] [x])
IReifiableConstraint
(reifyc [_ v r a]
(let [x (walk* r x)]
`(treec ~x ~cform))))
`defc` should intelligently fill in the details.