Clojure 散列映射的成员?

Clojure 散列映射的成员?,clojure,clojure-core.logic,Clojure,Clojure Core.logic,我想知道是否有其他人曾经需要并因此编码过类似membero的谓词,但用于哈希映射。当然,我可以在散列映射上使用(seq),但是如果它已经是一个LVar,它就不起作用了 如果我们称之为keyvalo,它的工作原理如下: (run* [q] (fresh [m kv] (== m {:a 2 :b 3}) (keyvalo kv m) (== q kv))) => ([:a 2] [:b 3]) 它可以定义为 (def

我想知道是否有其他人曾经需要并因此编码过类似
membero
的谓词,但用于哈希映射。当然,我可以在散列映射上使用
(seq)
,但是如果它已经是一个LVar,它就不起作用了

如果我们称之为
keyvalo
,它的工作原理如下:

(run* [q]
    (fresh [m kv]
           (== m {:a 2 :b 3})
           (keyvalo kv m)
           (== q kv)))
=> ([:a 2] [:b 3])
它可以定义为

(defn keyvalo [kv map]
  (fresh [s]
         (seqo s map)
         (membero kv s)))
但是我很难尝试编写一个
seqo
,这将在
(seqo[[:foo3]]]{:foo3})
中成功


谢谢

最简单的方法是
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* [q] (== (partial-map {:foo q}) {:foo 1 :bar 2}))
;=> (1)
(run* [q] (== (partial-map {q 1}) {:foo 1 :bar 2}))
;=> ()
但是,


请注意,
seqo
的一个问题是映射中的键没有顺序,而序列有顺序。因此,为了使
(seqo[:a1][:b2][:c3]{:a1:b2:c3})
成功,对于我正在使用的
(seq{:a1:b2:c3})实现,您必须测试
(seq{:a2:c3})
的任何排列例如,([:a1][:c3][:b2])
。你可以通过排列来解决这个问题,但这可能不是你想要的更大的地图。

最简单的方法是
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* [q] (== (partial-map {:foo q}) {:foo 1 :bar 2}))
;=> (1)
(run* [q] (== (partial-map {q 1}) {:foo 1 :bar 2}))
;=> ()
但是,

请注意,
seqo
的一个问题是映射中的键没有顺序,而序列有顺序。因此,为了使
(seqo[:a1][:b2][:c3]{:a1:b2:c3})
成功,对于我正在使用的
(seq{:a1:b2:c3})实现,您必须测试
(seq{:a2:c3})
的任何排列例如,([:a1][:c3][:b2])
。你可以用排列来解决这个问题,但这可能不是你想要的更大的地图