如何在clojure中将拉链移动到左/右节点?

如何在clojure中将拉链移动到左/右节点?,clojure,zipper,Clojure,Zipper,我正在clojure数据结构中编写一个业务流程决策树 (require clojure.zip :as z) (z/vector-zip [ :billed? [:yes [:check-bank-account] [:check-cash] ] [:send-out-email] ]) 当代码在第一个节点上漫游时,它将读取关键字并执行某些操作,结果将是True或False,然后我希望它进入

我正在clojure数据结构中编写一个业务流程决策树

(require clojure.zip :as z)

(z/vector-zip 
    [ :billed?  
        [:yes  
            [:check-bank-account] 
            [:check-cash] ] 
        [:send-out-email] ])
当代码在第一个节点上漫游时,它将读取关键字并执行某些操作,结果将是True或False,然后我希望它进入左True或右False节点

当我的代码以根节点开始,并调用与以下关联的函数:billed?它返回一个True,clojure如何进入:yes节点或:send out email节点?我以为只有z/down,而左边或右边只代表兄弟姐妹,不代表孩子的方向


非常感谢您抽出时间,并感谢您的任何想法

链式多拉链运动

下面是一个例子:

(require '[clojure.zip :as z])

(def zipper (z/vector-zip
              [:billed?
               [:yes
                [:check-bank-account]
                [:check-cash]]
               [:send-out-email]]))

(println (-> zipper z/down z/right z/down z/node))
(println (-> zipper z/down z/right z/down z/right z/down z/node))

链多拉链运动

下面是一个例子:

(require '[clojure.zip :as z])

(def zipper (z/vector-zip
              [:billed?
               [:yes
                [:check-bank-account]
                [:check-cash]]
               [:send-out-email]]))

(println (-> zipper z/down z/right z/down z/node))
(println (-> zipper z/down z/right z/down z/right z/down z/node))

拉链在数据结构中穿行,同时跟踪当前位置。要到达不同的节点,必须对同一个拉链应用一系列移动。创建拉链时,您的位置位于树的正上方:

(z/node tree)
=> [:billed? [:yes [:check-bank-account] [:check-cash]] [:send-out-email]]
因此,您可以使用z/down下降到树中,并使用z/node从拉链的位置获取当前节点:

(-> tree
    z/down
    z/node)
=> :billed?
如果从树的顶部向某个节点移动,可能只需要z/down和z/right,因为下降到子向量中会将您放置在最左边的子向量中。如果你把向量放在一条平直线上,想象z/right将光标移动到下一个元素,z/down将光标移动到向量内部,你会更容易想象到这一点

(-> tree
    z/down
    z/right
    z/node)
=> [:yes [:check-bank-account] [:check-cash]]

(-> tree
    z/down
    z/right
    z/right
    z/node)
=> [:send-out-email]
下面是一个示例,您可以通过根据事实地图评估键来遍历这棵树:

(def tree
  (z/vector-zip
    [:billed?
     [:wire-funds?
      [:check-bank-account]
      [:check-cash]]
     [:send-out-email]]))

(defn facts->action [facts]
  (loop [curr (z/down tree)]
    (let [node (z/node curr)]
      (if-let [fact (find facts node)]
        (if (val fact)
          (recur (-> curr z/right z/down)) ;; descend "left"
          (recur (-> curr z/right z/right z/down))) ;; descend "right"
        node))))

(facts->action {:billed? false})
=> :send-out-email
(facts->action {:billed? true :wire-funds? true})
=> :check-bank-account
(facts->action {:billed? true :wire-funds? false})
=> :check-cash

拉链在数据结构中穿行,同时跟踪当前位置。要到达不同的节点,必须对同一个拉链应用一系列移动。创建拉链时,您的位置位于树的正上方:

(z/node tree)
=> [:billed? [:yes [:check-bank-account] [:check-cash]] [:send-out-email]]
因此,您可以使用z/down下降到树中,并使用z/node从拉链的位置获取当前节点:

(-> tree
    z/down
    z/node)
=> :billed?
如果从树的顶部向某个节点移动,可能只需要z/down和z/right,因为下降到子向量中会将您放置在最左边的子向量中。如果你把向量放在一条平直线上,想象z/right将光标移动到下一个元素,z/down将光标移动到向量内部,你会更容易想象到这一点

(-> tree
    z/down
    z/right
    z/node)
=> [:yes [:check-bank-account] [:check-cash]]

(-> tree
    z/down
    z/right
    z/right
    z/node)
=> [:send-out-email]
下面是一个示例,您可以通过根据事实地图评估键来遍历这棵树:

(def tree
  (z/vector-zip
    [:billed?
     [:wire-funds?
      [:check-bank-account]
      [:check-cash]]
     [:send-out-email]]))

(defn facts->action [facts]
  (loop [curr (z/down tree)]
    (let [node (z/node curr)]
      (if-let [fact (find facts node)]
        (if (val fact)
          (recur (-> curr z/right z/down)) ;; descend "left"
          (recur (-> curr z/right z/right z/down))) ;; descend "right"
        node))))

(facts->action {:billed? false})
=> :send-out-email
(facts->action {:billed? true :wire-funds? true})
=> :check-bank-account
(facts->action {:billed? true :wire-funds? false})
=> :check-cash