Skip to content

Instantly share code, notes, and snippets.

@lgessler
Last active March 14, 2019 18:34
Show Gist options
  • Select an option

  • Save lgessler/50a097db40bd5f63f2ee3cfa550171dd to your computer and use it in GitHub Desktop.

Select an option

Save lgessler/50a097db40bd5f63f2ee3cfa550171dd to your computer and use it in GitHub Desktop.
Clojure macro demo for Anish
;; Preliminaries ------------------------------------------------------------
;; Clojure has namespaces. vars can be created in namespaces and referenced
;; from other namespaces.
(ns glam.db) ;; Switch into namespace glam.db
(var x 1) ;; define var glam.db/x
x ;; `x` evals to 1
;;=> 1
(ns glam.other) ;; switch to other namespace
x
;;ERROR: x is not defined in this namespace or imported
glam.db/x ;; can access other namespaces' vars this way
;;=> 1
;; can also import from other namespaces when entering a namespace
(ns glam.other
(require [glam.db :refer [x]]))
x
;;=> 1
;; The problem ------------------------------------------------------------
(ns glam.db
(:require [cljs.spec.alpha :as s])
(:require-macros [cljs.spec.alpha :as s]))
;; I often needed to write something like this. (::foo is syntax for "take
;; a keyword :foo and put the current namespace in front of it, so in this
;; case, ::foo => :glam.db/foo)
(def foo ::foo)
(s/def ::foo string?)
;; Writing this over and over is verbose. One approach would be to write
;; a function that does this:
(ns glam.db.common-functions
(defn def-with-spec
[key pred]
(def (-> key name symbol) key)
(s/def key pred))
;; But this doesn't work for reasons that have to do with how `def` is
;; implemented.
;; We need to write a macro instead:
(defmacro def-with-spec
[key pred]
`(do
(def ~(-> key name symbol) ~key)
(s/def ~key ~pred)))
;; Skipping over what all those symbols mean, this has the end result that
;; an invocation of it will expand to what we want:
(def-with-spec ::foo string?)
;;macroexpand=>
(do
(def foo ::foo)
(s/def ::foo string?))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment