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])
。你可以用排列来解决这个问题,但这可能不是你想要的更大的地图