Skip to content

Instantly share code, notes, and snippets.

@AlexBaranosky
Created December 20, 2011 01:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AlexBaranosky/1499725 to your computer and use it in GitHub Desktop.
Save AlexBaranosky/1499725 to your computer and use it in GitHub Desktop.
macroexpand-scan / macroexpand-reductions
(defn macroexpand-scan
([form]
(macroexpand-scan form []))
([form results]
(let [expanded (macroexpand-1 form)]
(if (= expanded form)
results
(recur expanded (conj results expanded))))))
;; Example
(defmacro a [s] `(defn ~(symbol s) [] ~s))
(macroexpand-scan `(a "f"))
; => [(clojure.core/defn f [] "f")
; (def f (clojure.core/fn ([] "f")))]
@amalloy
Copy link

amalloy commented Dec 20, 2011

Seems like this is a special case of something you might call steady-state: apply function f repeatedly, like iterate does, but stopping when you get a repeated value. Then (macroexpand-scan form) is just (steady-state macroexpand-1 form). As a bonus, (macroexpand form) is (last (steady-state macroexpand-1 form)).

@AlexBaranosky
Copy link
Author

Nice! Love the way you identified the higher-order function latent within this function. I think that's a great way to look at Clojure, always trying to extract out the higher order function in things, makes everything uber-composable. Thanks. See: https://gist.github.com/1501358 , (def macroexpand-scan (partial steady-state macroexpand-1))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment