打印:: keyword时禁止命名空间

时间:2015-11-01 13:51:36

标签: printing clojure keyword suppress

写作时

 (println '(:keyword1 :keyword2))

我得到以下输出:

  

(:keyword1:keyword2)

没关系。

但是当我写作

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

我明白了

  

(:namespace / keyword1:namespace / keyword2)

我想要

  

(:: keyword1 :: keyword2)

有可能吗?我只是使用大量关键字进行符号计算,我需要打印它们。

我试过这个:https://clojuredocs.org/clojure.pprint/*print-suppress-namespaces*但它没有帮助。

感谢您的任何建议。

3 个答案:

答案 0 :(得分:0)

Clojure中的印刷机械基于多种方法。可以利用它来更改命名空间关键字的打印方式。改变关键字的打印方式一般不太明智。

用于生成人类消费输出的多方法称为post。它需要两个参数 - 要打印的对象和输出的Writer。粗略地说,对正在打印的对象的类型执行调度。因此,可以为print-method类型重新定义clojure.lang.Keyword。该方法的print-method可用作参考。

还需要确定关键字是否具有命名空间组件 - 这是我们如何确定是否应该打印一个冒号或两个冒号。 default implementation类中的getNamespace方法可以完成这项工作。在这一点上,我们对Clojure实现细节的研究过于深入。自行承担风险。

(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

答案 1 :(得分:0)

好问题,我也觉得这种行为很烦人。如果您想使用相对本地的修复程序,请使用以下宏,该宏可以临时更改关键字的打印行为并抑制名称空间限定的地图符号,这在pprint中是令人讨厌的。请注意,这些更改将在宏的正文期间从所有线程可见,并且这将比普通方法慢得多地打印“关键字”。但是,大多数情况下这不是问题。

如果合格关键字的名称空间在当前名称空间中具有别名,它将打印具有该别名的关键字。

(defn short-keyword-print [^clojure.lang.Keyword kw, ^Writer w]
  (if-let [ns-str (.getNamespace kw)]
    (if-let [ns (find-ns (symbol ns-str))]
      (if (= ns *ns*)
        (.write w (str "::" (name kw)))
        (if-let [ns-alias (some #(when (= ns (val %)) (key %)) (ns-aliases *ns*))]
          (.write w (str "::" ns-alias "/" (name kw)))
          (.write w (str "::?/" (name kw)))))
      (.write w (str "::?/" (name kw))))
    (.write w (str ":" (name kw)))))

(defmacro with-short-keys [& body]
  `(binding [*print-namespace-maps* false]
     (let [old-kw-method# (get (methods print-method) clojure.lang.Keyword)]
       (. ~(with-meta `print-method {:tag 'clojure.lang.MultiFn})
         addMethod clojure.lang.Keyword short-keyword-print)
       (try
         ~@body
         (finally
           (. ~(with-meta `print-method {:tag 'clojure.lang.MultiFn})
             addMethod clojure.lang.Keyword old-kw-method#))))))

然后:

(require '[clojure.set :as set])

(with-short-keys
  (dorun
    (map println
      [:x                      ; unqualified
       ::x                     ; qualified with this namespace
       ::set/x                 ; qualified with aliased namespace
       :clojure.set/x          ; qualified with aliased namespace, but not using the alias
       :clojure.data/x         ; qualified with real but un-aliased namespace
       :some-other-namespace/x ; qualified with unreal un-aliased namespace
       ])))

此打印:

:x        ; unqualified
::x       ; qualified with this namespace
::set/x   ; qualified with aliased namespace
::set/x   ; qualified with aliased namespace, but not using the alias
::?/x     ; qualified with real but un-aliased namespace
::?/x     ; qualified with unreal un-aliased namespace

答案 2 :(得分:-1)

双冒号表示法的目的是将当前名称空间插入关键字。单冒号表示法的目的是创建一个没有命名空间的关键字。因此,提问毫无意义,

  

"我如何添加一个namspace然后假装它不在那里?"

最佳答案是决定是否要为关键字添加命名空间,然后选择合适的技术。

相关问题