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))))))