Skip to content

Instantly share code, notes, and snippets.

@ghoseb
Created April 16, 2012 09:32
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ghoseb/2397263 to your computer and use it in GitHub Desktop.
Save ghoseb/2397263 to your computer and use it in GitHub Desktop.
Cut macro from SRFI-26 in Clojure
;;; http://srfi.schemers.org/srfi-26/srfi-26.html
(defn ^:private cut*
[[a f] form]
(cond
(nil? form) [a f]
(seq? (first form))
(let [[arg-list xform] (cut* [[] '()] (first form))]
(recur [(reduce conj a arg-list) (concat f (list xform))] (next form)))
:else
(cond
(= (first form) '<>)
(let [g (gensym "d__")]
(recur [(conj a g) (concat f (list g))] (next form)))
(= (first form) '<...>)
(let [g (gensym "vd__")]
(recur [(reduce conj a ['& g]) (concat '(apply) f (list g))] (next form)))
:else
(recur [a (concat f (list (first form)))] (next form)))))
(defmacro cut
"The amazing cut macro."
[& forms]
(let [[arg-list xform] (cut* [[] '()] forms)]
`(fn ~arg-list
~xform)))
(comment
(map (cut assoc <> :foo 42) [{:a 1} {:b 2} {:c 3}])
;=> ({:foo 42, :a 1} {:foo 42, :b 2} {:foo 42, :c 3})
(map (cut <> <>) (repeat 2 [inc dec]) (repeat 42))
;=> (43 41 42 41)
;;; <...> is used for var args
(cut + 1 2 <...>)
;=> (fn [& args] (apply + 1 2 args)) ; macro-expansion
((cut + 1 2 <...>) 3 4 5 6)
;=> 21
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment