printingclojurekeywordsuppress

Suppress namespace when printing ::keyword


When I write

 (println '(:keyword1 :keyword2))

I get the following output:

(:keyword1 :keyword2)

and it's ok.

But when I write

(println '(::keyword1 ::keyword2))

I get this

(:namespace/keyword1 :namespace/keyword2)

And I want to get

(::keyword1 ::keyword2)

Is it possible? I just make symbolic computations with lots of keywords and I need to print them.

I tried this: https://clojuredocs.org/clojure.pprint/*print-suppress-namespaces* but it did not help.

Thank you for any advise.


Solution

  • The printing machinery in Clojure is based on multimethods. It is possible to take advantage of that in order to change how namespaced keywords are printed. Altering the way keywords are printed may not be wise in general though.

    The multimethod used to produce the output for human consumption is called print-method. It takes two arguments - the object to print and the output Writer. The dispatch is performed on the type of the object being printed, roughly speaking. Thus it is possible to re-define the print-method for clojure.lang.Keyword type. The default implementation of that method can be used as for reference.

    It is also necessary to find out if a keyword has a namespace component - this is how we can determine if we should print one colon or two. The getNamespace method in the Keyword class will do the job. At this point we are way too deep into Clojure implementation details. Proceed at your own risk.

    (import 'clojure.lang.Keyword)
    ;=> clojure.lang.Keyword
    (import 'java.io.Writer)
    ;=> java.io.Writer
    (defmethod print-method Keyword [^Keyword k, ^Writer w]
      (if (.getNamespace k)
        (.write w (str "::" (name k)))
        (.write w (str k))))
    ;=> #object[clojure.lang.MultiFn 0x24243e9f "clojure.lang.MultiFn@24243e9f"]
    (println ::foo)
    ;=> ::foo
    ;=> nil