在 Clojure 1.9-beta2 中,读者和作者现在支持紧凑的映射语法。在所有键都是具有相同名称空间的限定关键字的情况下,语法避免重复名称空间:
> (pr-str {:a/foo 1 :a/bar 2})
"#:a{:foo 1, :bar 2}"
将这样的序列化映射发送到 Clojure 1.8 进程时会导致问题:在那里运行的旧阅读器将无法读取它并抛出
java.lang.RuntimeException: Reader tag must be a symbol
。
幸运的是,打印机仅在动态变量
*print-namespace-maps*
为真时才执行此操作,并且默认情况下为假,因此我的应用程序可以继续在生产环境中工作。然而,REPL 将其设置为 true,因此当我在 REPL 中工作并执行一些最终向 Clojure 1.8 服务发送请求的操作时,它会失败。 如何在 REPL 中禁用新语法?
我想也许我可以在我的 repl 中添加
(set! *print-namespace-maps* false)
或将 {:user {:repl-options {:init (set! *print-namespace-maps* false)}}}
添加到我的 ~/.lein/profiles.clj 中,但这似乎不起作用。我认为原因可能是 REPL 使用 binding
为包括这个在内的一堆变量创建线程局部绑定,而 set!
不适用于局部变量绑定。
您可以为地图重新定义
print-method
,无论环境如何,它都应该有效。
(defmethod print-method clojure.lang.IPersistentMap [m, ^java.io.Writer w]
(#'clojure.core/print-meta m w)
(#'clojure.core/print-map m #'clojure.core/pr-on w))
使用
(set! *print-namespace-maps* false)
对我有用。 (但这已经是大约 5 年后的事了。)
这也有效,有时可能更理想:
(binding [*print-namespace-maps* false]
(pr-str {:a/foo 1 :a/bar 2}))
=> "{:a/foo 1, :a/bar 2}"
您还可以使用以下命令设置此设置:
(set! *print-namespace-maps* false)
并且至少会在 REPL 会话期间进行设置。