Create a gist now

Instantly share code, notes, and snippets.

(ns playingwithmacros.core
(:require [ :refer [browse-url]]
[clojure.pprint :as pp]
[clojure.core.strint :as strint]))
(defmacro my-simple-macro
"A docstring"
[first-arg second-arg & varargs]
"A return value of some kind")
(my-simple-macro a 2)
;; When does it actually run?
(defn test1 []
(my-simple-macro 1 2))
;; Add a println side-effect to the macro
;; Re-eval the defn
;;; Explanation by example
;;; Debug macro, from
(defmacro dbg
`(let [x# ~x]
(println '~x "=" x#)
;; Syntax-quote
`(1 2 3)
'(a b c)
`(a b c)
;; Namespace-qualified symbols
`(+ a b)
;; Unquote
(let [b 1]
`(a ~b))
(read-string "`(a ~b)")
;; Splice
(let [b ["THIS" "IS" "A" "VECTOR"]]
`(a ~b))
(let [b ["THIS" "IS" "A" "VECTOR"]]
`(a ~@b))
;; Gensyms
(defmacro why-gensyms?
`(let [x 1]
`(let [x 1]
(defmacro why-gensyms?
`(let [x# 1]
`(let [x# 1]
;;; Back to the source
;; What are &form and &env?
(defmacro env-and-form
[& body]
(dbg &env)
(dbg &form)
;; What's &form?
(env-and-form 23 4234 23)
;; What's &env?
(let [a 1
b 2]
;; Metadata on forms
(defmacro meta-env-and-form
[& body]
(dbg (meta &env))
(dbg (meta &form)))
(let [a 1
b 2]
(defn pprint-str
(with-out-str (pp/pprint x)))
(defmacro super-dbg
`(let [x# ~x]
(printf "dbg %s:%s> %s is %s\n"
~(:line (meta &form))
~(pr-str x)
(pprint-str x#))
(let [a 5]
(super-dbg a))
;;; Tools
(macroexpand '(fn [a]))
(macroexpand-1 '(fn [a]))
;;; Q: In what order are macros expanded?
(defmacro super-fn
[& body]
`(fn ~@body))
(macroexpand '(super-fn [a]))
(macroexpand-1 '(super-fn [a]))
;;; A: outer-first
'(let [a (fn [] blah)]))
;;; Q: When does the compiler perform macro-expansion?
;; macroexpand-1 gives a hint
;;; More useful macros!
(let [transforms {:keys keyword
:strs str
:syms identity}]
(defmacro keyed
"Create a map in which, for each symbol S in vars, (keyword S) is a
key mapping to the value of S in the current scope. If passed an optional
:strs or :syms first argument, use strings or symbols as the keys instead."
([vars] `(keyed :keys ~vars))
([key-type vars]
(let [transform (comp (partial list `quote)
(transforms key-type))]
(into {} (map (juxt transform identity) vars))))))
(let [a 1
b 2
c 3]
(keyed [a b c]))
;;; just for fun
(defmacro dbg-macro
(let [expansion (clojure.walk/macroexpand-all x)]
`(do (printf "dbg-macro> %s expands to %s\n"
~(pr-str x)
(dbg-macro (strint/<< "Chas is great times ~(+ 1 2)!"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment