最简单的将是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))))
这是不相关的,这意味着,虽然
(run 1 [q] (membero [:foo 1] q))
;=> (([:foo 1] . _0))
会给你一个列表,其中[:foo 1]
是成员(不要尝试此与run*
),
(run 1 [q] (keyvalo [:foo 1] q))
;=> IllegalArgumentException Don't know how to create ISeq from: clojure.core.logic.LVar
是反而会抛出异常。但是,这可能仍然足以满足您的需求。
例如,我们可以反转的地图现在
(run* [q] (== (partial-map {:foo q}) {:foo 1 :bar 2}))
;=> (1)
(run* [q] (== (partial-map {q 1}) {:foo 1 :bar 2}))
;=>()
但是,
(run* [q] (keyvalo [:foo q] {:foo 1 :bar 2}))
;=> (1)
(run* [q] (keyvalo [q 1] {:foo 1 :bar 2}))
;=> (:foo)
注意与seqo
这里有一个问题是,在地图的钥匙有没有顺序,而序列确实。因此,要使(seqo [[:a 1] [:b 2] [:c 3]] {:a 1 :b 2 :c 3})
成功,您需要测试(seq {:a 1 :b 2 :c 3})
的任何排列。例如,对于实现,我使用(seq {:a 1 :b 2 :c 3}) ;=> ([:a 1] [:c 3] [:b 2])
。你可以用排列来解决这个问题,但这可能不是你想要的更大的地图。