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})

ありがとう!

4

1 に答える 1

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は、マップ内のキーには順序がないのに対し、シーケンスには順序があることに注意してください。したがって、 forを成功させるには、 For the implementation I am using の(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])

于 2013-08-21T17:04:25.273 に答える