com.github.jlangch.venice.old.walk.venice Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of venice Show documentation
Show all versions of venice Show documentation
Venice, a sandboxed Lisp implemented in Java.
;;;; __ __ _
;;;; \ \ / /__ _ __ (_) ___ ___
;;;; \ \/ / _ \ '_ \| |/ __/ _ \
;;;; \ / __/ | | | | (_| __/
;;;; \/ \___|_| |_|_|\___\___|
;;;;
;;;;
;;;; Copyright 2017-2024 Venice
;;;;
;;;; Licensed under the Apache License, Version 2.0 (the "License");
;;;; you may not use this file except in compliance with the License.
;;;; You may obtain a copy of the License at
;;;;
;;;; http://www.apache.org/licenses/LICENSE-2.0
;;;;
;;;; Unless required by applicable law or agreed to in writing, software
;;;; distributed under the License is distributed on an "AS IS" BASIS,
;;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;;; See the License for the specific language governing permissions and
;;;; limitations under the License.
;;;; Venice walk functions
;;;; Thanks to Stuart Sierra and his clojure walk project
;;;; (https://github.com/clojure/clojure/blob/master/src/clj/clojure/walk.clj).
;;;; Venice's walk builds heavily on Stuart Sierra's work.
(ns walk)
(defn-
^{ :arglists '("(walk inner outer form)")
:doc """
Traverses form, an arbitrary data structure. inner and outer are
functions. Applies inner to each element of form, building up a
data structure of the same type, then applies outer to the result.
Do not call this function directly use walk/postwalk or
walk/prewalk instead.
""" }
walk [inner outer form]
(cond
(list? form) (outer (apply list (map inner form)))
(map-entry? form) (outer (map-entry (inner (key form)) (inner (val form))))
(coll? form) (outer (into (empty form) (map inner form)))
:else (outer form)))
(defn
^{ :arglists '("(postwalk f form)")
:doc """
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.
"""
:examples (list
"""
(walk/postwalk (fn [x] (println "Walked:" (pr-str x)) x)
'(1 2 {:a 1 :b 2}))
""") }
postwalk [f form]
(walk/walk (partial postwalk f) f form))
(defn
^{ :arglists '("(prewalk f form)")
:doc """
Performs a depth-last, pre-order traversal of form. Calls f on
each sub-form, uses f's return value in place of the original.
"""
:examples (list
"""
(walk/prewalk (fn [x] (println "Walked:" (pr-str x)) x)
'(1 2 {:a 1 :b 2}))
""") }
prewalk [f form]
(walk/walk (partial prewalk f) identity (f form)))
(defn
^{ :arglists '("(postwalk-dump form)")
:doc """
Demonstrates the behavior of postwalk by printing each form
as it is walked. Returns the form.
"""
:examples (list "(walk/postwalk-dump '(1 2 {:a 1 :b 2}))") }
postwalk-dump [form]
(walk/postwalk (fn [x] (println "Walked:" (pr-str x)) x) form))
(defn
^{ :arglists '("(prewalk-dump form)")
:doc """
Demonstrates the behavior of prewalk by printing each form
as it is walked. Returns the form.
"""
:examples (list "(walk/prewalk-dump '(1 2 {:a 1 :b 2}))") }
prewalk-dump [form]
(walk/prewalk (fn [x] (println "Walked:" (pr-str x)) x) form))
(defn
^{ :arglists '("(keywordize-keys form)")
:doc "Recursively transforms all map keys from strings to keywords."
:examples (list """(walk/keywordize-keys '(1 2 {"a" 1 "b" 2}))""") }
keywordize-keys [form]
(let [f (fn [[k v]] (if (string? k) [(keyword k) v] [k v]))]
;; only apply to maps
(walk/postwalk (fn [x] (if (map? x) (into {} (map f x)) x)) form)))
(defn
^{ :arglists '("(stringify-keys form)")
:doc "Recursively transforms all map keys from keywords to strings."
:examples (list """(walk/stringify-keys '(1 2 {:a 1 :b 2}))""") }
stringify-keys [form]
(let [f (fn [[k v]] (if (keyword? k) [(name k) v] [k v]))]
;; only apply to maps
(walk/postwalk (fn [x] (if (map? x) (into {} (map f x)) x)) form)))
(defn
^{ :arglists '("(prewalk-replace key-map form)")
:doc """
Recursively transforms form by replacing keys in key-map with
their values. Does replacement at the root of the tree first.
"""
:examples (list
"(walk/prewalk-replace {:a :A :b :B} '(1 2 :a :b))",
"(walk/prewalk-replace {:a :A :b :B} '(1 2 {:a 1 :b 2}))" ) }
prewalk-replace [key-map form]
(walk/prewalk (fn [x] (if (contains? key-map x) (key-map x) x)) form))
(defn
^{ :arglists '("(postwalk-replace key-map form)")
:doc """
Recursively transforms form by replacing keys in key-map with
their values. Does replacement at the leaves of the tree first.
"""
:examples (list
"(walk/postwalk-replace {:a :A :b :B} '(1 2 :a :b))",
"(walk/postwalk-replace {:a :A :b :B} '(1 2 {:a 1 :b 2}))" ) }
postwalk-replace [key-map form]
(walk/postwalk (fn [x] (if (contains? key-map x) (key-map x) x)) form))
(defn
^{ :arglists '("(macroexpand-all form)")
:doc "Recursively expands all macros in the form."
:examples (list
"(walk/macroexpand-all '(and true true))",
"(walk/macroexpand-all '(and true (or true false) true))"
"(walk/macroexpand-all '(let [n 5] (cond (< n 0) -1 (> n 0) 1 :else 0)))" ) }
walk/macroexpand-all [form]
(walk/prewalk (fn [x] (if (list? x) (macroexpand x) x)) form))