Robert Campbell
Robert Campbell

Reputation: 6958

Why is this contradictory clojure.core.logic/featurec result being returned?

...and how can I avoid it?

(run* [q]
   (featurec q {:a 1})
   (featurec q {:a 2})))

returns

((_0
  :-
  (clojure.core.logic/featurec _0 {:a 2})
  (clojure.core.logic/featurec _0 {:a 1})))

which I understand to mean that the _0 map must contain at least the :a 1 key-value pair AND the :a 2 key-value pair. This seems contradictory as :a can't map to both 1 and 2 unless we used MultiMaps. I can't read it as :a 1 OR :a 2 because the constraints I specify are a conjunction. I would have imagined that the result should be () because the constraints are contradictory; there is no value for q that can satisfy these constraints.

I must be reading the result incorrectly.

Upvotes: 2

Views: 138

Answers (1)

nberger
nberger

Reputation: 3659

Yes, it's contradictory. But it's what it is: There's no map that can unify with {:a 1} and {:a 2} at the same time.

run*, all, fresh all introduce a conjunction (AND) among its constraints. If you want a disjunction (OR) you could introduce a conde.

Perhaps your question is: Why core.logic isn't being able to "see" the contradiction and return an empty result set? I don't know exactly. But maybe it has to do with the fact that even if we remove one of the constraints, we don't get a "grounded" result:

(run* [q]
   (featurec q {:a 1}))

;=> ((_0 :- (clojure.core.logic/featurec _0 {:a 1})))

It reads as: anything, as far as it's a map which includes the [:a 1] entry. And I think that's the correct result.

Upvotes: 1

Related Questions