3

I was curious about what certain macros were doing and tried to call (macroexpand-1) to get more info. However, I'm a little confused about how to expand the built-in macros in ClojureScript, particularly the macros in the cljs.core namespace. According to the docs, ClojureScript macros are written in Clojure and therefore have to be tested in a Clojure REPL (instead of a ClojureScript REPL), which is where I've been trying this from.

Running lein repl from my ClojureScript project's directory, I've tried this:

=> (require 'cljs.compiler)
=> (require 'cljs.core)
=> (macroexpand-1 '(cljs.core/int 99.9))
(macroexpand-1 '(cljs.core/int 99.9))
(cljs.core/int 99.9)

Why does that return (cljs.core/int 99.9)? Based on the ClojureScript source, shouldn't that macro expand to something like (bit-or ~x 0)?

When I expand non-ClojureScript macros, such as (macroexpand-1 '(when (even? 2) (println "2 is even"))), the expansion seems to work fine.

Seems like I'm missing something conceptually...

2 Answers 2

5

Most likely you're using a ClojureScript version predating this commit which introduces the int macro. Try adding [org.clojure/clojurescript "0.0-1835"] to your :dependencies.

Also, while this is not relevant here, in general you should use ClojureScript's macroexpand-1 rather than Clojure's for tests like this one:

(require '[cljs.compiler :as comp]) ; must be required before cljs.core
(require '[cljs.core :as core])     ; the macros live here
(require '[cljs.analyzer :as ana])  ; macroexpand-1 lives here

;; ClojureScript's macroexpand-1 takes an environment as its first
;; argument; here's a useful initial environment:
(ana/macroexpand-1 {:locals {} :context :expr :ns 'cljs.user} '(int 5))
;= (cljs.core/bit-or 5 0)
Sign up to request clarification or add additional context in comments.

4 Comments

Interestingly, I didn't expect ClojureScript to have its own macroexpand-1, since it doesn't have its own defmacro.
Just realized that Clojure's macroexpand-1 actually should work for you here, see my comment on dnolen's answer. Since the commit introducing the int macro is dated 22 Feb 2013, you might simply be using an older release; with 0.0-1835 (the latest as of this time) you should see the result you expect. It is still true that ClojureScript's macroexpand-1 is needed in general, since the ClojureScript environment may be relevant in more complex cases.
Edited the answer to include the above comment. As for ClojureScript having its own macroexpand-1: it's needed because ClojureScript needs its own logic for expander lookup (see cljs.analyzer/get-expander). It also convinces the expander that the current namespace is in fact called whatever the current ClojureScript namespace is called in an effort to make it somewhat aware of the actual ClojureScript environment it outputs code into.
Gotcha. This all makes a lot more sense now. While trying to figure why I couldn't see the int macro, I had updated my ClojureScript dependency just before you posted your original answer. The coincidence made it appear that I had to use ClojureScript's macroexpand-1, but you're right: at least for int it was simply a case of not having a recent enough jar.
4

There is no compiler macro for int is all.

2 Comments

Actually there is, it's just that one must use the correct macroexpand-1.
Hm, actually the regular macroexpand-1 should also work in this case (the ClojureScript environment is irrelevant here, except for the presence of the bit-or macro, but this is defined earlier in cljs/core.clj). If the OP doesn't see this, he's probably using a version predating the introduction of the int macro (in this commit). So this answer is quite correct for older releases. Sorry for the confusion.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.