我相信我在core.logic中解构地图时遇到了问题。我有以下代码:
... used clojure.core.logic
... required clojure.core.logic.arithmetic as logic.arithmetic.
(def hand ({:rank 9, :suit :hearts}
{:rank 13, :suit :clubs}
{:rank 6, :suit :spades}
{:rank 8, :suit :hearts}
{:rank 12, :suit :clubs}))
(run* [q]
(fresh [v w x y z] ;;cards
(== q [v w x y z])
(membero v hand)
(membero w hand)
(membero x hand)
(membero y hand)
(membero z hand)
(fresh [a b c d e] ;;ranks
(== {:rank a} v)
(== {:rank b} w)
(== {:rank c} x)
(== {:rank d} y)
(== {:rank e} z)
(logic.arithmetic/>= a b)
(logic.arithmetic/>= b c)
(logic.arithmetic/>= c d)
(logic.arithmetic/>= d e))
(distincto q)))
返回空列表(),表示找不到匹配项。我认为这是代码中(== {:rank a} v)部分的问题。我试图简单地返回q,其中q是地图的矢量:降序排列。
答案 0 :(得分:7)
现在可以使用最新的core.logic版本0.8.3编写一个更简洁的解决方案:
(ns cards
(:refer-clojure :exclude [==])
(:use [clojure.core.logic])
(:require [clojure.core.logic.fd :as fd]))
(def hand
[{:rank 9, :suit :hearts}
{:rank 13, :suit :clubs}
{:rank 6, :suit :spades}
{:rank 8, :suit :hearts}
{:rank 12, :suit :clubs}])
(defn ranko [card rank]
(featurec card {:rank rank}))
(run* [v w x y z :as q]
(permuteo hand q)
(fresh [a b c d e]
(ranko v a) (ranko w b) (ranko x c)
(fd/>= a b) (fd/>= b c)
(ranko y d) (ranko z e)
(fd/>= c d) (fd/>= d e)))
答案 1 :(得分:0)
显然你必须在地图上进行完全匹配。这意味着您可以创建垃圾变量来捕获您不感兴趣的任何值。看起来很奇怪,但还可以。
(run* [q]
(fresh [v w x y z] ;;cards
(== q [v w x y z])
(membero v hand)
(membero w hand)
(membero x hand)
(membero y hand)
(membero z hand)
(fresh [a b c d e, f g h i j] ;;ranks, garbage
(== {:rank a :suit f } v)
(== {:rank b :suit g } w)
(== {:rank c :suit h } x)
(== {:rank d :suit i } y)
(== {:rank e :suit j } z)
(logic.arithmetic/>= a b)
(logic.arithmetic/>= b c)
(logic.arithmetic/>= c d)
(logic.arithmetic/>= d e))
(distincto q)))
最后,这里有一个稍微简洁,更快,更乱码的版本。
(run* [q]
(fresh [v w x y z] ;;cards
(permuteo hand q)
(== q [v w x y z])
(fresh [a b c d e, f g h i j] ;;ranks, garbage
(== {:rank a :suit f } v)
(== {:rank b :suit g } w)
(logic.arithmetic/>= a b)
(== {:rank c :suit h } x)
(logic.arithmetic/>= b c)
(== {:rank d :suit i } y)
(logic.arithmetic/>= c d)
(== {:rank e :suit j } z)
(logic.arithmetic/>= d e))))
答案 2 :(得分:0)
如果您不需要引用逻辑变量,则实际上不需要命名它:
(== {:rank a :suit (lvar)} v)
我发现自己越来越多地使用(lvar)
。它通常使代码比一次性的未使用变量更清晰,但我希望有更好的方法来表达它。