Search code examples
clojurescript

Clojurescript - how to use/import macros in REPL (figwheel)


I can't seem to use macros in clojurescript REPL.

I define macro in macros.clj:

(ns clojurescripting.macros)

(defmacro increment [x]
  `(+ 1 ~x))

Then I use it in core.cljs

(ns ^:figwheel-hooks clojurescripting.core
    (:require-macros [clojurescripting.macros]))

(defn main []
      (js/alert (clojurescripting.macros/increment 0)))

(main)

The code actually uses increment macro, because it gives alert with correct output.

I run repl with clojure -A:fig:build.

When I try to use macros in REPL, I can't access the macro - there is no clojurescripting.core/increment, and I can't access clojurescripting.macros there.

Another question: Is this possible in any REPL? It seems possible in general, as book Learning Clojurescript provide almost identical example, and proceeds to evaluate it in the REPL.

PS

This is not a duplicate of this question - it is most likely outdated, and the accepted answer is cryptic (I'm not even sure what bREPL is, and whether figwheel uses it).


Solution

  • Yes, you can use macros in the REPL, just as you can in code.

    The qualified name of the macro in your example is clojurescripting.macros/increment (not clojurescripting.core/increment), and, presuming the macros namespace has been loaded, you can call the macro (just as is done in the example in your code). Here is an example:

    cljs.user=> (clojurescripting.macros/increment 0)
    1
    

    If the macros namespace has not been loaded, you can do that from the REPL by using require-macros. Here's an example, that would work even if none of your namespaces were loading the macros namespace:

    cljs.user=> (require-macros 'clojurescripting.macros)
    nil
    cljs.user=> (clojurescripting.macros/increment 0)
    1
    

    You can also use namespace aliases

    cljs.user=> (require-macros '[clojurescripting.macros :as macros])
    nil
    cljs.user=> (macros/increment 0)
    1
    

    and refer macro vars

    cljs.user=> (require-macros '[clojurescripting.macros :refer [increment]])
    nil
    cljs.user=> (increment 0)
    1
    

    All of this should work directly in the REPL.

    In fact, all of the variations discussed at https://clojurescript.org/guides/ns-forms should work in the REPL, using require-macros in lieu of :require-macros and require in lieu of :require, etc.