Back
postwalk (clj)
(source)function
(postwalk f form)
Performs a depth-first, post-order traversal of form. Calls f on
each sub-form, uses f's return value in place of the original.
Recognizes all Clojure data structures. Consumes seqs as with doall.
Examples
clojure
(ns clojure.test-clojure.reader
(:use clojure.test)
(:use [clojure.instant :only [read-instant-date
read-instant-calendar
read-instant-timestamp]])
(:require clojure.walk
[clojure.edn :as edn]
[clojure.test.generative :refer (defspec)]
[clojure.test-clojure.generators :as cgen]
[clojure.edn :as edn])
(:import [clojure.lang BigInt Ratio]
java.io.File
java.util.TimeZone))
(let [a 5]
^:added-metadata
(defn add-5
[x]
(reduce + x (range a))))"
stream (clojure.lang.LineNumberingPushbackReader.
(java.io.StringReader. code))
top-levels (take-while identity (repeatedly #(read stream false nil)))
expected-metadata '{ns {:line 1, :column 1}
:require {:line 2, :column 3}
resource {:line 3, :column 21}
let {:line 5, :column 1}
defn {:line 6, :column 3 :added-metadata true}
reduce {:line 9, :column 5}
range {:line 9, :column 17}}
verified-forms (atom 0)]
(doseq [form top-levels]
(clojure.walk/postwalk
#(when (list? %)
(is (= (expected-metadata (first %))
(meta %)))
(is (->> (meta %)
vals
(filter number?)
(every? (partial instance? Integer))))
(swap! verified-forms inc))
form))
;; sanity check against e.g. reading returning ()
(is (= (count expected-metadata) @verified-forms))))
clojure
(ns clojure.test-clojure.clojure-walk
(:require [clojure.walk :as w])
(:use clojure.test))
(deftest t-postwalk-replace
(is (= (w/postwalk-replace {:a :b} [:a {:a :a} (list 3 :c :a)])
[:b {:b :b} (list 3 :c :b)])))
(deftest t-postwalk-order
(is (= (let [a (atom [])]
(w/postwalk (fn [form] (swap! a conj form) form)
[1 2 {:a 3} (list 4 [5])])
@a)
[1 2
:a 3 [:a 3] {:a 3}
4 5 [5] (list 4 [5])
[1 2 {:a 3} (list 4 [5])]])))
(deftest walk-mapentry
"Checks that walk preserves the MapEntry type. See CLJ-2031."
(let [coll [:html {:a ["b" 1]} ""]
f (fn [e] (if (and (vector? e) (not (map-entry? e))) (apply list e) e))]
(is (= (list :html {:a (list "b" 1)} "") (w/postwalk f coll)))))
metabase/metabase
(ns metabase.lib.query-test
(:require
#?@(:cljs ([metabase.test-runner.assert-exprs.approximately-equal]))
[clojure.test :refer [are deftest is testing]]
[clojure.walk :as walk]
[metabase.lib.convert :as lib.convert]
[metabase.lib.core :as lib]
[metabase.lib.metadata :as lib.metadata]
[metabase.lib.query :as lib.query]
[metabase.lib.test-metadata :as meta]
[metabase.lib.test-util :as lib.tu]
[metabase.lib.util :as lib.util]
[metabase.util.malli :as mu]))
(deftest ^:parallel type-fill-in-converted-test
(is (=? {:stages [{:fields [[:field {:base-type :type/BigInteger
:effective-type :type/BigInteger}
(meta/id :venues :id)]]
:filters [[:= {} [:expression {:base-type :type/Integer :effective-type :type/Integer} "math"] 2]]}]}
(lib/query
meta/metadata-provider
(lib.convert/->pMBQL {:type :query
:database (meta/id)
:query {:source-table (meta/id :venues)
:expressions {"math" [:+ 1 1]}
:fields [[:field (meta/id :venues :id) nil]]
:filters [[:= [:expression "math"] 2]]}}))))
(testing "filling in works for nested join queries"
(let [clause (as-> (lib/expression lib.tu/venues-query "CC" (lib/+ 1 1)) $q
(lib/join-clause $q [(lib/= (meta/field-metadata :venues :id)
(lib/expression-ref $q "CC"))]))
query (lib/join lib.tu/venues-query clause)
;; Make a legacy query but don't put types in :field and :expression
converted-query (lib.convert/->pMBQL
(walk/postwalk
(fn [node]
(if (map? node)
(dissoc node :base-type :effective-type)
node))
(lib.convert/->legacy-MBQL query)))]
(is (=? {:stages [{:joins [{:conditions [[:= {}
[:field {:base-type :type/BigInteger} (meta/id :venues :id)]
[:expression
{}
;; TODO Fill these in?
#_{:base-type :type/Integer}
"CC"]]]}]}]}
metabase/metabase
(ns metabase.sync.sync-metadata.fields.fetch-metadata-test
(:require
[clojure.test :refer :all]
[clojure.walk :as walk]
[medley.core :as m]
[metabase.models.database :refer [Database]]
[metabase.models.table :refer [Table]]
[metabase.sync.sync-metadata :as sync-metadata]
[metabase.sync.sync-metadata.fields.fetch-metadata :as fetch-metadata]
[metabase.test.mock.toucanery :as toucanery]
[metabase.util :as u]
[toucan2.core :as t2]
[toucan2.tools.with-temp :as t2.with-temp]))
(let [transactions-table-id (u/the-id (t2/select-one-pk Table :db_id (u/the-id db), :name "transactions"))
remove-ids-and-nil-vals (partial walk/postwalk #(if-not (map? %)
%
;; database-position isn't stable since they are
;; defined in sets. changing keys will change the
;; order in the set implementation. (and position depends on database-position)
(m/filter-vals some? (dissoc % :id :database-position :position))))]
(remove-ids-and-nil-vals (#'fetch-metadata/our-metadata (t2/select-one Table :id transactions-table-id))))))))
clojure/clojure
(ns clojure.test-clojure.clojure-walk
(:require [clojure.walk :as w])
(:use clojure.test))
(deftest t-postwalk-replace
(is (= (w/postwalk-replace {:a :b} [:a {:a :a} (list 3 :c :a)])
[:b {:b :b} (list 3 :c :b)])))
(deftest t-postwalk-order
(is (= (let [a (atom [])]
(w/postwalk (fn [form] (swap! a conj form) form)
[1 2 {:a 3} (list 4 [5])])
@a)
[1 2
:a 3 [:a 3] {:a 3}
4 5 [5] (list 4 [5])
[1 2 {:a 3} (list 4 [5])]])))
(deftest walk-mapentry
"Checks that walk preserves the MapEntry type. See CLJ-2031."
(let [coll [:html {:a ["b" 1]} ""]
f (fn [e] (if (and (vector? e) (not (map-entry? e))) (apply list e) e))]
(is (= (list :html {:a (list "b" 1)} "") (w/postwalk f coll)))))
clojure/clojurescript
(ns cljs.walk-test
(:require [cljs.test :refer-macros [deftest testing is]]
[clojure.walk :as w]))
(deftest t-postwalk-replace
(is (= (w/postwalk-replace {:a :b} [:a {:a :a} (list 3 :c :a)])
[:b {:b :b} (list 3 :c :b)])))
(deftest t-postwalk-order
(is (= (let [a (atom [])]
(w/postwalk (fn [form] (swap! a conj form) form)
[1 2 {:a 3} (list 4 [5])])
@a)
[1 2
:a 3 [:a 3] {:a 3}
4 5 [5] (list 4 [5])
[1 2 {:a 3} (list 4 [5])]])))
(deftest walk-mapentry
"Checks that walk preserves the MapEntry type. See CLJS-2909."
(let [coll [:html {:a ["b" 1]} ""]
f (fn [e] (if (and (vector? e) (not (map-entry? e))) (apply list e) e))]
(is (= (list :html {:a (list "b" 1)} "") (w/postwalk f coll)))))
babashka/babashka
(ns loom.test.alg
(:require [loom.graph :refer [graph weighted-graph digraph weighted-digraph nodes
successors remove-nodes add-nodes edges
add-edges]]
[loom.alg :refer [pre-traverse post-traverse pre-span topsort
bf-traverse bf-span bf-path
bf-path-bi dijkstra-path dijkstra-path-dist
dijkstra-traverse dijkstra-span johnson
all-pairs-shortest-paths connected-components
connected? scc strongly-connected? connect
dag? shortest-path loners bellman-ford
bipartite-color bipartite? bipartite-sets
coloring? greedy-coloring prim-mst-edges
prim-mst-edges prim-mst astar-path astar-dist
degeneracy-ordering maximal-cliques
subgraph? eql? isomorphism?]]
[loom.derived :refer [mapped-by]]
clojure.walk
#?@(:clj [[clojure.test :refer :all]]
:cljs [cljs.test]))
#?@(:cljs [(:require-macros [cljs.test :refer (deftest testing are is)])]))
(let [vecs->sets #(clojure.walk/postwalk
(fn [x]
(if-not (map? x)
x
(reduce
(fn [m [k v]] (assoc m k (if (vector? v) (set v) v)))
{}
x)))
%)]
(is (= (vecs->sets
{1 {1 [5], 5 [3], 3 [6 2], 2 [4], 6 [10]}
2 {2 [4], 4 [10]}
3 {3 [1 6 2], 1 [5], 2 [4], 6 [10]}
4 {4 [10], 10 [2]}
5 {5 [3], 3 [1 6 2], 2 [4], 6 [10]}
6 {6 [1 10], 1 [5], 10 [2], 5 [3], 2 [4]}
7 {4 [10], 8 [11 9], 7 [8], 9 [3 5], 11 [4 2], 3 [1 6]}
8 {4 [10], 8 [11 9], 9 [7 3 5], 11 [4 2], 3 [1 6]}
9 {8 [11], 6 [10], 7 [8], 2 [4], 9 [7 3 5], 3 [1 6 2]}
10 {10 [2], 2 [4]}
11 {11 [4 2], 4 [10]}})
(vecs->sets (all-pairs-shortest-paths g13))))))