(defn my-cljs-targeting-reader-fn [form]
`(.foo ~form))
The behaviour of Clojurescript’s reader is mostly the same as the Clojure Reader but with notable differences with respect to tagged literals.
Tagged Literals allow users to extend the reader. See the Clojure Reader guide on tagged literals for an introduction.
Imagine we have a custom tagged literal #foo/bar
. We need to define reader functions for the contexts where we
want to read it, which will be one or both of:
Clojurescript source code or REPL input
in a JS runtime when reading (EDN) data
In this situation Reader functions execute in Clojure and should return either a form which represents valid Clojurescript (similar to a Clojurescript macro) or a literal such as a string or number.
(defn my-cljs-targeting-reader-fn [form]
`(.foo ~form))
This contrasts with Clojure reader functions, which execute like a normal function.
(defn my-clj-targeting-reader-fn [form]
(.foo form))
In order to read custom tagged literals in Clojurescript source, namespaced symbols are associated with reader functions in a data_readers.cljc file as described in the Clojure Reader guide. If the same tagged literal is to be used for both Clojure and Clojurescript, reader conditionals may be used in data_readers.cljc if the reader functions will be different for targeting Clojure vs Clojurescript.
When using the EDN reader, reader functions are just regular Clojurescript functions (meaning not macro-like as when reading source).
(def custom-tag-map {'foo/bar (fn [x] (.foo x))})
(cljs.edn/read-string
{:readers custom-tag-map}
"#foo/bar \"abc\"")
An alternative to cljs.edn/read-string
is cljs.reader/read-string
. This just calls cljs.edn/read-string
, but note
that the default tag mapping includes mappings read from data_readers.cljc. For the following to work, data_readers.cljc
must contain and entry with key 'foo/bar
and a value that resolves to a regular Clojurescript function.
(cljs.reader/read-string "#foo/bar \"abc\"")
Original author: Henry Widd