clojure - 如何在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
(False) 节点。
当我的代码从根节点开始,并调用一些与之关联的函数:billed?
返回 aTrue
时,clojure 怎么会走进:yes
节点或:send-out-email
节点?我以为只有z/down
一段时间,left
或者right
只是为了兄弟姐妹而不是为了孩子的方向。
非常感谢您的宝贵时间并感谢您的任何想法
解决方案
拉链在跟踪当前位置的同时遍历数据结构。要到达不同的节点,您必须对同一个拉链应用一系列移动。创建拉链后,您的位置就在树的正上方:
(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
and 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
推荐阅读
- javascript - 更新 React 组件中的默认值
- bash - 当未提供 --stable 选项时, sort -n 是否可以预测地处理关系?如果有,怎么做?
- groovy - 有没有办法在 Liferay 中获取工作流提交的表单字段?
- python - 具有多个连接的 Sqlalchemy 查询,包括非直接多对多关系
- c# - Unity C# 错误'cs0116'“命名空间不能直接包含字段或方法等成员”
- javascript - 在 mouseenter 上隐藏 div - 但保留它
- entity-framework-core - ef core plus 是否支持带减号的批量更新?
- python - python tkinter 计算器项目
- javascript - 将可排序列表添加到空列表中并删除可排序列表而不重复
- python - 如何在 Python 中执行伴随敏感性(最好通过 CVODE)