Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
按路径模式访问clojure.zip树_Clojure_Pattern Matching_Zipper - Fatal编程技术网

按路径模式访问clojure.zip树

按路径模式访问clojure.zip树,clojure,pattern-matching,zipper,Clojure,Pattern Matching,Zipper,假设我有一个我想访问的树,其中应该包括修改已访问项目的可能性,所有与路径匹配的项目 (def visit-path [:b :all :x :all]) 其中我使用:all作为通配符来匹配所有子节点。在下面的示例树中 (def my-tree {:a "a" :b {:b-1 {:x {:b-1-1 "b11" :b-1-2 "b12"}} :b-2 {:x {:b-2-1 "b21"}}}}) 这将是一个项目 [:b

假设我有一个我想访问的树,其中应该包括修改已访问项目的可能性,所有与路径匹配的项目

(def visit-path [:b :all :x :all])
其中我使用
:all
作为通配符来匹配所有子节点。在下面的示例树中

(def my-tree
  {:a "a"
   :b
   {:b-1
    {:x
     {:b-1-1 "b11"
      :b-1-2 "b12"}}
    :b-2
    {:x
     {:b-2-1 "b21"}}}})
这将是一个项目

  • [:b-1-1“b11”]
  • [:b-1-2“b12”]
  • [:b-2-1“b21”]
使用clojure core是否有一种优雅的方法


仅供参考,我通过创建自己的模式访问者解决了这个问题

(defn visit-zipper-pattern
  [loc pattern f]
但是,尽管这个函数在一般情况下是可用的,但它非常复杂,既有使用堆栈的递归,也有尾部调用递归。所以当调用这个方法时

(visit-zipper-pattern (map-zipper my-tree) visit-path
  (fn [[k v]] [k (str "mod-" v)]))
使用
map zippers
from,它将树转换为

{:a "a"
 :b {:b-1
     {:x
      {:b-1-1 "mod-b11"
       :b-1-2 "mod-b12"}}
     :b-2
     {:x
      {:b-2-1 "mod-b21"}}}}

以下操作将起作用-请注意:1)在处理
:所有
关键点时,它可能会分配不需要的对象;2)您需要决定如何处理边缘情况,如非地图叶子上的
:所有

(defn traverse [[k & rest-ks :as pattern] f tree]
  (if (empty? pattern)
    (f tree)
    (if (= k :all)
      (reduce #(assoc %1 %2 (traverse rest-ks f (get tree %2)))
              tree (keys tree))
      (cond-> tree (contains? tree k)
              (assoc k (traverse rest-ks f (get tree k)))))))

要获得更有效的解决方案,可能最好按照上面的建议使用。

您知道吗?谢谢@Clojuremobly这就是我现在使用的解决方案,尽管从specter github页面上看,作者对我来说有点太过自负了。:)谢谢这比我的解决方案更简洁,尽管(也许是因为)它没有使用clojure.zip。与此同时,正如建议的那样,我转而使用specter(虽然是为了灵活性,而不是——在我的情况下——为了性能),但这个问题是关于一个优雅的clojure.core解决方案的——你的解决方案是什么!