Quick Guide: Inspecting ClojureScript Compiler Outputs in REPL

Quick Guide: Inspecting ClojureScript Compiler Outputs in REPL

Inspecting the Compiled ClojureScript Code

When I first started learning Clojurescript, I often thought about how the code I'm writing translates to Javascript. This was because I had spent a few years prior primarily working on Typescript; hence, it was the reference I had at the time.

I figured there must be an easy way to see the translation result, and I asked around what's the default way to do this in the REPL. As far as I know, I might as well have been the first one asking about this since there was no quick answer available (usually there is).

Since Clojurescript is compiled into Javascript, I thought the most straightforward way to do this would be to use the plain JS interop.

Plain JS Interop

The toString() method of Function instances returns a string representing the source code of this function.

MDN Docs

Knowing that toString method prints out the source code for functions. We can view the compiled source by simply calling the .toString. In Javascript, it'd be as simple as:

>> function piece_of_code(){ 
>>  console.log("hello")
>> };
undefined
>> piece_of_code.toString()
'function piece_of_code(){ 
  console.log("hello")
}'

The same approach works in the CLJS context, and we can make the result read better by just printing out the value.

(.toString piece-of-code)
"function cljs$user$piece_of_code(){\nreturn console.log(\"hello\");\n}"

(defn print-src [f]
  (println (str f)))

(print-src piece-of-code)
;; => 
;; function app$core$piece_of_code(){
;;   return console.log("hello");
;; }

CLJS Compiler Option

But after some digging, I found the fantastic video: "Mike Fikes explains the ClojureScript Compiler" and learned that a dynamic CLJS compiler variable *print-fn-bodies* does the same thing without the extra work. Later, I discovered that Mike also has a blog post explaining how to do this.

(set! *print-fn-bodies* true)

(do piece-of-code)
;; => #object[app$core$piece_of_code "function app$core$piece_of_code(){
;;   return console.log("hello");
;; }"]

With this approach, it is enough to set the variable, and you're good to go.

Conclusion

I think it is good to know how to do this when you're working with CLJS. You might not need to drop into the JS level that often, but knowing how to do it quickly without using external tools makes all the difference in the dev flow, and even if you don't need to, it's good to know how to do it just for curiosity's sake.

Ultimately, the code we are dealing with is just JavaScript, and we can use the same functions we'd be using on the JS development. On top of that, if you're working in a browser context, it's also possible to view and interact with the compiled code in the browser console.

Thanks for reading. I hope you found this helpful. I recommend taking a look at Mike's blog to learn more about Clojurescript.