Skip to content

Instantly share code, notes, and snippets.

@shofetim
Created June 5, 2015 03:38
Show Gist options
  • Save shofetim/065260ed22c1dc55f009 to your computer and use it in GitHub Desktop.
Save shofetim/065260ed22c1dc55f009 to your computer and use it in GitHub Desktop.
;; Story:
;; I have an EDN data structure from an external API
;; I extract several patterns of records from it.
;; I would like to treat the patterns as data, pass them around, modify them etc.
(def sample-data {:tracks {:items [1 2 3 4 5]}})
(def pattern [:tracks :items count])
;; Thread first -> should be what I need, but I need to "apply" it...
(apply -> (cons sample-data pattern)) ;; Can't take value of a macro: #'clojure.core/->
;; So make a new macro that reuses ->
(defmacro get->> [data pattern]
`(-> ~data ~@pattern))
(macroexpand-1 '(get->> sample-data pattern))
;; Don't know how to create ISeq from: clojure.lang.Symbol
@zentrope
Copy link

zentrope commented Jun 5, 2015

See this: http://stackoverflow.com/questions/5277451/clojure-macro-puzzle-expanding-sequence-in-macro-args

Basically, macro-expansion doesn't have access to the run-time environment, so can't expand pattern which is defined in the def.

(get->> sample-data [:tracks :items count])

works, but:

(get->> sample-data pattern)

won't.

All the macro can see when it's expanding is a symbol 'pattern because macro args aren't expanded, so the contents of it just isn't there. In effect, we (I'm tolstoy on IRC) were trying to ~@symbol that wasn't anything but a symbol.

@zentrope
Copy link

zentrope commented Jun 5, 2015

This works, though:

(defn get->> [data pattern]
  (reduce (fn [a f] (f a)) data pattern))

so don't even need a macro! I imagine there could be similar versions for thread-last vs thread-first.

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