如何将拉链移动到 clojure 中的 left/right 节点?
How to move zipper to left/right node in clojure?
我正在用 clojure 数据结构编写一棵树(业务流程决策树)。
(require clojure.zip :as z)
(z/vector-zip
[ :billed?
[:yes
[:check-bank-account]
[:check-cash] ]
[:send-out-email] ])
当代码在第一个节点上行走时,它会读取关键字并执行某些操作,结果将是 True 或 False,然后我希望它走进 left
( True) 或 right
(假)节点 .
当我的代码从根节点开始,并调用一些与 :billed?
关联的函数时 return a True
,clojure 怎么会进入 :yes
节点,或者:send-out-email
节点?我以为只有 z/down
,而 left
或 right
仅供兄弟姐妹使用,不适用于 children.
非常感谢您的宝贵时间,感谢您的任何想法
链接多个拉链运动。
这是一个例子:
(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))
Zipper 在跟踪当前位置的同时遍历数据结构。要到达不同的节点,您必须对同一个拉链应用一系列移动。创建拉链后,您的位置就在树的正上方:
(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
将光标移动到 内部 [=29],则更容易想象这一点=]一个向量。
(-> 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
我正在用 clojure 数据结构编写一棵树(业务流程决策树)。
(require clojure.zip :as z)
(z/vector-zip
[ :billed?
[:yes
[:check-bank-account]
[:check-cash] ]
[:send-out-email] ])
当代码在第一个节点上行走时,它会读取关键字并执行某些操作,结果将是 True 或 False,然后我希望它走进 left
( True) 或 right
(假)节点 .
当我的代码从根节点开始,并调用一些与 :billed?
关联的函数时 return a True
,clojure 怎么会进入 :yes
节点,或者:send-out-email
节点?我以为只有 z/down
,而 left
或 right
仅供兄弟姐妹使用,不适用于 children.
非常感谢您的宝贵时间,感谢您的任何想法
链接多个拉链运动。
这是一个例子:
(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))
Zipper 在跟踪当前位置的同时遍历数据结构。要到达不同的节点,您必须对同一个拉链应用一系列移动。创建拉链后,您的位置就在树的正上方:
(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
将光标移动到 内部 [=29],则更容易想象这一点=]一个向量。
(-> 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