步行vs地图处理seq

mur*_*a52 11 clojure

据我所知,walk和map都将函数应用于seq.(步行也允许应用outer函数后处理).然而,使用一个而不是另一个的惯用案例是什么?

set*_*hev 10

语义map基本上是:将函数应用于集合中的每个项目,并按顺序返回结果:

(map inc #{0 1 2}) ;outputs (when realized) (1 2 3)
Run Code Online (Sandbox Code Playgroud)

请注意,输入是一个集合,但输出是一个序列.

walk的语义基本上是:创建一个相同类型的集合,其中每个项目已被inner该项目的函数值替换,返回应用于outer新集合的结果:

(walk inc identity #{0 1 2}) ;outputs #{1 2 3}
Run Code Online (Sandbox Code Playgroud)

如果你看一下步行API(在其他功能的源代码http://richhickey.github.com/clojure/clojure.walk-api.html),你可以看到如何进行递归行走以及(或只是使用其他功能).

就成语而言,我不确定.但是walk更复杂,所以你可能应该坚持map在你不需要walk提供语义的情况下.


A. *_*ebb 7

将函数应用于seq是map的工作.当您必须遍历并递归地遍历整个结构时,请使用walk.

walks的一些例子可以在ClojureDocs中找到,也可以在REPL中找到,例如(user/clojuredocs clojure.walk/postwalk).许多例子是教学和可能,应做mapfor(有时reduce)在实践中.

a的典型用例walk是当您希望以递归方式处理嵌套结构时.这可能有用的一些例子是clojure.walk命名空间本身,例如看看(source clojure.walk/keywordize-keys).[注意,如果您想要迭代或随意处理它,请使用拉链(或者tree-seq对于一些更简单的迭代情况).]

想到的另一个例子是解释解析树:

(require '[clojure.walk :as w])

(def t [+ [* [- 6 2] [/ 9 3]] [* 2 [+ 7 8]]])

(w/postwalk #(if (and (coll? %) (fn? (first %))) (apply (first %) (next %)) %) t)
;=> 42
Run Code Online (Sandbox Code Playgroud)

也许有用的,例如,替换fn?allowed-fn?等,以评估表达式,而不是调用太强大的eval编译器:

(eval t) ;=> [#<core$_PLUS_ ... ] 
Run Code Online (Sandbox Code Playgroud)

糟糕,表单是列表,而不是向量:

(def s (w/postwalk #(if (coll? %) (apply list %) %) t))
s ;=> (#<core$_PLUS_ ... )
(eval s) ;=> 42
Run Code Online (Sandbox Code Playgroud)

啊,请注意这里的另一种用法walk- 递归地将结构从嵌套向量更改为嵌套列表.

冥想的一个反复例子:

(require '[clojure.walk :as w])

(def s1 (range 8))
s1 ;=> (0 1 2 3 4 5 6 7)
(map inc s1)
;=> (1 2 3 4 5 6 7 8)
(w/postwalk #(if (number? %) (inc %) %) s1)
;=> (1 2 3 4 5 6 7 8)

(def s2 (partition 2 s1))
s2 ;=> ((0 1) (2 3) (4 5) (6 7))
(map (partial map inc) s2)
;=> ((1 2) (3 4) (5 6) (7 8))
(w/postwalk #(if (number? %) (inc %) %) s2)
;=> ((1 2) (3 4) (5 6) (7 8))

(def s3 (partition 2 s2))
s3 ;=> ((0 1) (2 3) (4 5) (6 7))
(map (partial map (partial map inc)) s3)
;=> (((1 2) (3 4)) ((5 6) (7 8)))
(w/postwalk #(if (number? %) (inc %) %) s3)
;=> (((1 2) (3 4)) ((5 6) (7 8)))

(def s4 (partition 2 s3))
s4 ;=> ((((0 1) (2 3)) ((4 5) (6 7))))
(map (partial map (partial map (partial map inc))) s4)
;=> ((((1 2) (3 4)) ((5 6) (7 8))))
(w/postwalk #(if (number? %) (inc %) %) s4)
;=> ((((1 2) (3 4)) ((5 6) (7 8))))
Run Code Online (Sandbox Code Playgroud)