Easiest would be to project
(run* [q]
(fresh [m]
(== m {:foo 1 :bar 2}) ; m is an LVar
(project [m] ; but when bound values are projected
(membero q (seq m))))) ; seq can be used
;=> ([:foo 1] [:bar 2])
(defn keyvalo [kv m] (project [m] (membero kv (seq m))))
This is non-relational, which means that while
(run 1 [q] (membero [:foo 1] q))
;=> (([:foo 1] . _0))
will give you a list for which [:foo 1]
is a member (don't try this with run*
),
(run 1 [q] (keyvalo [:foo 1] q))
;=> IllegalArgumentException Don't know how to create ISeq from: clojure.core.logic.LVar
is going to throw an exception instead. But, this probably will still suffice for your purposes.
For example, we can invert a map now
(run* [q] (== (partial-map {:foo q}) {:foo 1 :bar 2}))
;=> (1)
(run* [q] (== (partial-map {q 1}) {:foo 1 :bar 2}))
;=> ()
But,
(run* [q] (keyvalo [:foo q] {:foo 1 :bar 2}))
;=> (1)
(run* [q] (keyvalo [q 1] {:foo 1 :bar 2}))
;=> (:foo)
Note that a problem with seqo
here is that the keys in the map have no order, whereas a sequence does. Therefore, for (seqo [[:a 1] [:b 2] [:c 3]] {:a 1 :b 2 :c 3})
to succeed, you would have test for any permutation of (seq {:a 1 :b 2 :c 3})
For the implementation I am using (seq {:a 1 :b 2 :c 3}) ;=> ([:a 1] [:c 3] [:b 2])
, for example. You could work around this with permutations, but that's likely not what you want for larger maps.