One of the best ways to up your cljs game is to read other people’s code. When I first got started reading/writing cljs, I was confused when I saw #js.

First of all, #js is a reader literal. Reader literals are used by the cljs reader and can be used to read in a specific data type. Consider a javascript array:

=> (require '[cljs.reader :as reader])

=> (array 1 2 3)
#js [1 2 3] ;;a javascript array

=> (type (reader/read-string "#js [1 2 3]"))
#<function Array() { [native code] }>

You’ll see #js when doing JS interop. For example, Om provides a cljs wrapper of React, and you can see #js used to pass proper javascript objects to React:

  ;;create a javascript object
  #js {:onClick
          (println "I can read!" (:foo data))
          (om/update-state! owner :count inc))}

One thing to note is that the literal only applies at the top level (i.e. won’t deeply apply to nested structures):

;;WRONG - probably wanted js objects all the way down
#js {:jsObj {:not-a :object}}

;;CORRECT - js objects all the way down
#js {:jsObj #js {:proper :object}}

cljs actually includes four built-in literals: #inst, #js, #queue, and #uuid.

=> (js/Date.)
#inst "2015-06-09T05:38:26.146-00:00"
=> (type (reader/read-string "#inst \"2015-06-09T05:38:26.146-00:00\""))
#<function Date() { [native code] }>

=> (into cljs.core.PersistentQueue.EMPTY [1 2 3])
#queue [1 2 3]
=> (type (cljs.reader/read-string "#queue [1 2 3]"))

=> (UUID. "random-string-here") ;; cljs-version <= 0.0-3269
#uuid "random-string-here"
=> (uuid "random-string-here") ;; cljs-version >= 0.0-3308
#uuid "random-string-here"
=> (type (reader/read-string "#uuid \"random-string-here\""))

Now, when you see a reader literal, you’ll understand exactly what you’re looking at. If you’re interested in the implementation details, check out the source.

Find this post useful? Share the love!

Join the Newsletter

Subscribe and never miss a post.

    I won't send you spam. Unsubscribe at any time.

    Powered By ConvertKit

    Recent Posts