问题
在CLJS(非自托管的)中,读取器字面量在Clojure中求值,但通常必须发射CLJS,这可能需要在运行时可用的其他命名空间。这限制了CLJS中读取器字面量的有用性,因为字面量的用户必须了解所有数据读取器实现的要求,并手动在他们项目的代码顶部附近包含必要的requires。
在Clojure和自托管的CLJS中,这种情况发生得较少,因为读取时间和求值时间共享相同的运行时。它们可以直接需求所需的命名空间并返回实例而不是代码。
建议
在非自托管的cljs中,将data_readers.cljc和data_readers.cljs中提到的命名空间包含在依赖树的某个高度,以便数据读取器可以满足它们在读取时发出的代码的运行时要求。
具体来说,如下代码应该可以工作:
{foo myfoons/foo-reader}
`
(ns myfoons
;; bar 仅在评估时间需要
#?(: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)
;; 注意 #foo 的 impl 需要 bar,
;; 但我们无需在这里显式地要求 bar
(def my-foo #foo 123)
`
实现
(link: ~dnolen)建议在{{cljs.closure}}命名空间中在构建管道某处添加提到的data_reader-mentioned命名空间。
实现问题
- 在从data_readers.cljc收集读取器以确定要加载的额外cljs-time命名空间时,data_readers.cljc文件应该作为{{:clj}}(与读取器和{{cljs.closure/get-data-readers}}相同)评估,还是作为{{:cljs}}(与自托管相同)评估?我们应该寻找{{data_readers.cljs}}吗?
- 是否应将数据读取器映射中提到的命名空间作为“主要”命名空间的依赖项添加,还是应将特定标签的命名空间作为使用该标签的各个命名空间的依赖项添加,或者还有其他方法?