2013-08-20 189 views
1

我想知道是否有其他人需要,因此编码,如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 [[:foo 3]] {:foo 3})

谢谢!

回答

1

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