Skip to content

Instantly share code, notes, and snippets.

@shaunlebron
Created April 27, 2023 23:37
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 shaunlebron/99a3e8754f2cfaa2a83f027799c30e5e to your computer and use it in GitHub Desktop.
Save shaunlebron/99a3e8754f2cfaa2a83f027799c30e5e to your computer and use it in GitHub Desktop.
(defmacro =>>
"Makes ->> faster if the first form is a collection, and the last form is `sequence`, `into`, or `reduce`"
;; adapted from: https://github.com/divs1210/streamer/blob/master/src/streamer/core.clj
[coll & xforms-and-term]
(let [[xforms term] ((juxt butlast last) xforms-and-term)]
(cond
;; sequence
(or (= term 'sequence)
(and (list? term)
(= (first term) 'sequence)))
(do
(assert (= 0 (count (rest term))) "`=>> sequence` must have no args")
`(sequence (comp ~@xforms) ~coll))
;; into
(and (list? term)
(= (first term) 'into))
(let [[_ to] term]
(assert (= 1 (count (rest term))) "`=>> into` must have one arg")
`(into ~to (comp ~@xforms) ~coll))
;; reduce
(and (list? term)
(= (first term) 'reduce))
(let [[_ f init] term]
(assert (#{1 2} (count (rest term))) "`=>> reduce` must have one or two args")
(if init
`(transduce (comp ~@xforms) ~f ~init ~coll)
`(transduce (comp ~@xforms) ~f ~coll)))
:else
(throw (ex-info (format "=>> must end with `(sequence)`, `(into ...)`, or `(reduce ...)`. got `%s` instead" term)
{:term term})))))
(comment
(require '[criterium.core :refer [quick-bench]])
(quick-bench
(->> (range 10)
(filter even?)
(map #(Math/sqrt %))
(reduce *))) ;; => 341 ns
(quick-bench
(=>> (range 10)
(filter even?)
(map #(Math/sqrt %))
(reduce *)))) ;; => 206 ns
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment