postwalk recursively traverses an arbitrarily nested Clojure data structure in depth-first, post-order fashion. It applies a one-argument function to every node only after recursively processing that node’s children, making it useful for transforming or reducing completed branches. section 8.4.2
Its contract is small but important:
- Call (postwalk f form) with a one-argument function f and any form, including nil. section 8.4.2
- Visit collections recursively and invoke f on collections and non-collection values alike. section 8.4.2
- Usually preserve the input collection type, although transformations performed by f determine the output. section 8.4.2
- Potentially throw UnsupportedOperationException for recognized collection types missing required operations, such as bean’s missing empty method. section 8.4.2
Observe post-order traversal
(require '[clojure.walk :refer [postwalk-demo]]) (postwalk-demo [1 [2 [3]] 4]) ;; Walked: 1 ;; Walked: 2 ;; Walked: 3 ;; Walked: [3] ;; Walked: [2 [3]] ;; Walked: 4 ;; Walked: [1 [2 [3]] 4] ;; [1 [2 [3]] 4] The leaves appear first; each containing vector appears only after its nested branch has been visited. section 8.4.1
Evaluate an expression tree
Represent a computation as maps containing :function and :children, then evaluate each node after its children: (postwalk evaluate (compound-interest-data 7.2 5000 2)) ;; 5771.936460924754 Because child expressions are resolved first, the parent function receives completed operands. section 8.4.2
Choose postwalk when processing a parent depends on transformed or evaluated descendants. Choose prewalk when the function must alter a node before descending, such as preventing traversal into a branch; both can produce equal values while producing different side effects. section 8.4.2
