#'clojure.core/some-> and the Power of Macros
Eric Bailey
Written on 2 January, 2015
Updated on 18 December, 2023
Tags: clojure, lisp, metaprogramming
Homoiconicity, and metaprogramming, and macros! Oh my!
In 2015, my love for these elegant weapons will undoubtedly grow fonder.
See also: #'clojure.core/some->
source on GitHub
(comment ;; #'clojure.core/some-> is one my favorite Clojure macros. (some-> (meta #'clojure.core/some->) :doc println) ;; When expr is not nil, threads it into the first form (via ->), ;; and when that result is not nil, through the next etc (macroexpand '(some-> (meta #'clojure.core/some->) :doc println)) (let* [G__2986 (meta (var clojure.core/some->)) G__2986 (if (clojure.core/nil? G__2986) nil (clojure.core/-> G__2986 :doc)) G__2986 (if (clojure.core/nil? G__2986) nil (clojure.core/-> G__2986 println))] G__2986) ;; Rewritten more readably to illustrate the point: (let [example (meta #'clojure.core/some->) example (when-not (nil? example) (:doc example)) example (when-not (nil? example) (println example))] example) ;; Which brings me to another of my scattered thoughts, ;; Clojure has the #'clojure.core/when-not macro, but ;; for some reason, I find myself wanting to use 'unless, ;; as in Common Lisp: (defmacro unless (condition &rest body) `(if (not ,condition) (progn ,@body))) ;; What better excuse to start writing my own macros? (ns fastidious.macros) (defmacro unless [condition & body] `(if (not ~condition) (do ~@body))) ;; Side bonus: I used my desire for 'unless to drive ;; my experiments in integrating macros in ClojureScript, ;; with underwhelming success. It just works. (ns client.core (:require-macros [fastidious.macros :refer [unless]])) (let [lisp-is-lame? false] (unless lisp-is-lame? (println "IFL Lisp.") (println "Next up: /c[ad]{1,5}r/"))))