'Turn off *print-namespace-maps* in repl

With Clojure 1.9-beta2, the reader and writer now support a compact syntax for maps. The syntax avoids repeating the namespace in the case where all the keys are qualified keywords with the same namespace:

> (pr-str {:a/foo 1 :a/bar 2})
"#:a{:foo 1, :bar 2}"

That causes problem when sending such a serialized map to a Clojure 1.8 process: the old reader running there will fail to read it and throw a java.lang.RuntimeException: Reader tag must be a symbol.

Luckily, the printer only does this when the dynamic variable *print-namespace-maps* is truthy, and it's falsey by default, so my app continues to work in production. However, the REPL sets it to true, so when I work in the REPL and do something that ends up sending a request to a Clojure 1.8 service, it fails. How can I disable the new syntax in the REPL also?

I thought that maybe I could just (set! *print-namespace-maps* false) in my repl or add {:user {:repl-options {:init (set! *print-namespace-maps* false)}}} to my ~/.lein/profiles.clj, but that doesn't seem to work. I think the reason may be that the REPL uses binding to create thread-local bindings for a bunch of variables including this one, and set! does not work for local variable bindings.



Solution 1:[1]

You can redefine print-method for maps, which should work regardless of environment.

(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))

Solution 2:[2]

Using (set! *print-namespace-maps* false) works for me. (But this is some 5 years later.)

This also works, and can sometimes be more desirable:

(binding [*print-namespace-maps* false] 
  (pr-str {:a/foo 1 :a/bar 2}))
=> "{:a/foo 1, :a/bar 2}"

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 madstap
Solution 2 PEZ