2012-05-15 18 views
2

我要通过这个article on Tree Visitors in Clojure和整个下面的例子来:步行/ postwalk使用

(def data [[1 :foo] [2 [3 [4 "abc"]] 5]]) 

(walk/postwalk #(do (println "visiting:" %) %) data) 

什么是postwalk做外在形式?我无法理解它的实用性。如何以及为什么使用了街道?任何解释将不胜感激。

+0

你是从格鲁吉亚来的吗? Murtaz是乔治亚州的一个着名的名字。 –

+0

不是来自印度 – murtaza52

+0

ok :)这可能是西亚地区的通用名称。抱歉,不主张。 –

回答

4

我不知道你是问什么#()意思或做什么的目的(form1 form2)的意思,所以我会回答这两个问题。

#()是声明匿名函数的简写。当你将某个函数传递给另一个函数时,匿名函数很有用。

为了说明,看这在repl

; define an anonymous function 
user=> #(+ %1 %2) 
#<user$eval68$fn__69 [email protected]> 

; is equivalent to 
user => (fn [a b] (+ a b)) 
#<user$eval1951$fn__1952 [email protected]> 

; furthermore, you could then assign your anonymous function to a var 
(def f #(+ %1 %2)) 

; is equivalent to 
(defn f [a b] (+ a b)) 

user=> (#(+ %1 %2) 1 2) 
3 

user=> (f 1 2) 
3 

%n指的参数的位置的参数的函数,其中n装置nth参数,从1开始作为进一步的速记可以使用%至请参阅适用于单个arg匿名函数的第一个参数。这就是你的例子。

所以,你的例子是相当于

(def data [[1 :foo] [2 [3 [4 "abc"]] 5]]) 

(defn f [x] (do (println "visiting:" x) x)) 

(walk/postwalk f data) 

这里的do是一种特殊形式,其中,从文档:

(做exprs *) 评估了顺序,并返回表达式最后的价值。如果没有提供表达式,则返回nil。

事实上defn已经有一个隐含的做,所以我上面的例子实际上并不需要做...

; your example is equivalent to: 

(def data [[1 :foo] [2 [3 [4 "abc"]] 5]]) 

(defn f [x] (println "visiting:" x) x) 

(walk/postwalk f data) 
+0

感谢您回答问题。然而,我很抱歉,我想问问什么是走秀。 – murtaza52

2

我有同样的问题,今天,找到这个necrotopik。也许以后更好更新。找到这个对clojure api reference

postwalk 功能 用法:(postwalk F体) 执行形式的深度优先,后序遍历。在 每个子表格上调用f,使用f的返回值代替原来的值。 识别除排序映射之外的所有Clojure数据结构。 与doall一样消耗seqs。

这也使得example from clojuredocs事情更清晰:

(use 'clojure.walk) 
(let [counter (atom -1)] 
(postwalk (fn [x] 
      [(swap! counter inc) x]) 
       {:a 1 :b 2})) 

    => [6 {2 [[0 :a] [1 1]], 5 [[3 :b] [4 2]]}] 

所以,postwalk替换功能的结果,每一个子窗体。它用于使用新值更新嵌套结构。这就是为什么结果函数最后包含x或%的原因。将结果添加到结果会导致更​​加嵌套的结构。

在上面的例子中,它被看作是遍历嵌套地图结构的深度。它首先处理地图中最深的元素,然后继续向上,然后潜伏到下一个表格,然后再次上升并完成整个表格的最后一步。