Skip to content

Instantly share code, notes, and snippets.

@frenchy64
Last active February 22, 2022 02:45
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 frenchy64/bcb14ce0e42afb55117b80cbe4dd4b2b to your computer and use it in GitHub Desktop.
Save frenchy64/bcb14ce0e42afb55117b80cbe4dd4b2b to your computer and use it in GitHub Desktop.
Macrovich case explanation

https://github.com/cgrand/macrovich/commit/9f5bd6f2777f0494e46ce7c430fd1fcef2690475#r67189464

@viebel Without this, you need to write macros like this:

(defmacro my-macro []
  `(macros/case
     :clj 1
     :cljs 2))

The problem this extra branch solves is to be able to write the following (without a syntax quote):

(defmacro my-macro []
  (macros/case
    :clj 1
    :cljs 2))

This is used in xforms.

In terms of implementation, this specifically targets the case where the form in literally inside the defmacro. ie., this won't work:

(defn helper []
  (macros/case
    :clj 1
    :cljs 2))
(defmacro my-macro []
  (helper))

However, based on the following trick, this will work:

(defn helper [&env]
  (macros/case
    :clj 1
    :cljs 2))
(defmacro my-macro []
  (helper &env))

So there are two steps:

  1. You need to know if you're currently expanding inside a defmacro. Since &env is always in lexical scope in a defmacro, the (contains? &env '&env) is a crude "am I being expanded inside a defmacro?" check.

  2. Now we need choose which implementation to expand for. The strategy here access the &env in the current defmacro call:

(defmacro my-macro []
  (if (:ns &env) 1 2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment