Problem
In CLJS (non-self-hosted) a reader literal is evaluated in Clojure but often must emit CLJS which may depend on other namespaces being available at runtime. This limits the usefulness of reader literals in CLJS because the user of the literal must be aware of the requirements of all data reader implementations and manually include the necessary requires near the top of his project's code.
This problem happens less often in Clojure and self-hosted CLJS because read-time shares the same runtime as eval-time. They can require the namespaces they need directly and return instances rather than code.
Proposal
In non-self-hosted cljs, require namespaces mentioned by data_readers.cljc and data_readers.cljs somewhere high in the dependency tree so that data readers can satisfy the runtime requirements for code they emitted at read time.
Concretely, code like this should work:
{foo myfoons/foo-reader}
`
(ns myfoons
;; bar is only needed at eval time
#?(:cljs (:require bar)))
#?(:clj
;; This is only needed at read time
;; It emits code that requires bar at eval time
(defn foo-reader [x] `(bar/make-bar x)))
`
`
(ns my.app-code)
;; Note the impl of #foo requires bar,
;; but we did not need to require bar explicitly here
(def my-foo #foo 123)
`
Implementation
(link: ~dnolen) suggests adding data_reader-mentioned namespaces to the dependency tree somewhere in the build pipeline in the {{cljs.closure}} namespace.
Implementation Questions
- When gathering readers from data_readers.cljc to determine additional cljs-time namespaces to load, should the data_readers.cljc files be evaluated as {{:clj}} (same as the reader and {{cljs.closure/get-data-readers}}) or {{:cljs}} (same as self-host)? Should we look for {{data_readers.cljs}}?
- Should the namespaces mentioned in the data reader map be added as dependencies to the "main" namespace, or should a particular tag's namespace be added as a dependency to the individual namespaces that use that tag, or something else?