【问题标题】:How do I de-structure a map in core.logic?如何在 core.logic 中解构地图?
【发布时间】:2013-04-04 21:07:02
【问题描述】:

我相信我在解构 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 是按 :rank 降序排列的地图向量。

【问题讨论】:

    标签: clojure clojure-core.logic


    【解决方案1】:

    现在可以使用最新的 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)))
    

    【讨论】:

      【解决方案2】:

      显然您必须在地图上进行完全匹配。这意味着您可以创建垃圾变量来捕获您不感兴趣的任何内容的值。看起来很奇怪,但没关系。

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

      【讨论】:

      • 现在可以使用featurec 仅匹配地图的一部分。我还建议在算术上使用新的有限域命名空间。
      【解决方案3】:

      如果你不需要引用逻辑变量,你实际上不需要命名它:

      (== {:rank a :suit (lvar)} v)
      

      我发现自己越来越多地使用(lvar)。它通常使代码比一次性未使用的变量更清晰,但我确实希望有更好的方式来表达这一点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-20
        相关资源
        最近更新 更多