Quick Guide: Inspecting ClojureScript Compiler Outputs in REPL

Toni VäisänenToni Väisänen
3 min read

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.

0
Subscribe to my newsletter

Read articles from Toni Väisänen directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Toni Väisänen
Toni Väisänen

Software engineer @ Metosin Ltd Need help with a project, contact: first.last@metosin.com As a 𝐜𝐨𝐧𝐬𝐮𝐥𝐭𝐚𝐧𝐭, I help clients find technical solutions to their business problems and facilitate communication between the stakeholders and the technical team. As a 𝐟𝐮𝐥𝐥-𝐬𝐭𝐚𝐜𝐤 𝐝𝐞𝐯𝐞𝐥𝐨𝐩𝐞𝐫, I build technical solutions for client's problems from user interfaces, and backend services to infrastructure-as-code solutions. As a 𝐦𝐚𝐜𝐡𝐢𝐧𝐞 𝐥𝐞𝐚𝐫𝐧𝐢𝐧𝐠 𝐞𝐧𝐠𝐢𝐧𝐞𝐞𝐫, I create, validate and deploy predictive models.