【问题标题】:How to move zipper to left/right node in clojure?如何在clojure中将拉链移动到左/右节点?
【发布时间】:2019-01-27 13:35:55
【问题描述】:

我正在用 clojure 数据结构编写树(业务流程决策树)。

(require clojure.zip :as z)

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

当代码在第一个节点上行走时,它会读取关键字并执行某些操作,结果是真或假,然后我希望它走进left(真)或right(假)节点.

当我的代码从根节点开始,并调用一些与:billed? 关联的函数时,它返回一个True,clojure 怎么会进入:yes 节点或:send-out-email 节点?我以为只有z/down,而leftright 仅供兄弟姐妹使用,不用于儿童指导。

非常感谢您的宝贵时间并感谢您的任何想法

【问题讨论】:

    标签: clojure zipper


    【解决方案1】:

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

    (z/node tree)
    => [:billed? [:yes [:check-bank-account] [:check-cash]] [:send-out-email]]
    

    因此您可以使用z/down 下到树中,并使用z/node 从拉链的位置获取当前节点:

    (-> tree
        z/down
        z/node)
    => :billed?
    

    如果你从树的顶部走向某个节点,你可能只需要z/downz/right,因为下降到一个子向量会将你放在最左边的孩子。如果您将向量排成一条直线并想象z/right 只是将光标移动到下一个元素,然后z/down 将光标移动到向量内部,则更容易想象这一点。 p>

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

    【讨论】:

      【解决方案2】:

      链式多个拉链动作。

      这是一个例子:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-22
        • 2022-01-18
        相关资源
        最近更新 更多