如何找到符号的完全限定名称空间?

时间:2013-04-18 06:36:14

标签: clojure namespaces

如果我有一个符号,其命名空间是别名,如q / w,我怎样才能找到它的实际命名空间,比如actual.namespace / w?

我知道resolve会给我完全限定的var,但我不知道如何获取var的命名空间。

我能做的最好的事情是:

 (defn fqns [s] (str (get (ns-aliases *ns*) (symbol (namespace s)))))
肯定有一种更简单的方法吗?

2 个答案:

答案 0 :(得分:8)

您可以获取符号的名称空间对象,如下所示(如果您想将ns的名称作为字符串,那么只需在末尾调用str):

(defn fqns [s] (->> (resolve s) meta :ns))

答案 1 :(得分:2)

符号本身与任何名称空间对象没有直接连接;它的命名空间部分只是一个实习字符串。只有当它被resolve d时,才会将此字符串视为查找Var的实际命名空间的名称。 (特别是,您可以创建符号foo/bar而无需创建名称空间foo或将foo注册为名称空间的别名。)因此,您需要通过{{1}或者自己做部分工作。

在第一种情况下,您可以说(在最新版本的Clojure中;或者您可以跳过表示属性访问的连字符 - 而不是resolve,使用-ns - 向后兼容)

ns

这解析了一个Var对象,然后从其(.. (resolve s) -ns -name) 字段中提取对其命名空间的引用,最后从其ns字段中提取命名空间的符号名称。 (请注意,namenamespace函数不起作用,因为Vars和名称空间不实现name。)

问题文本中的函数也很好,尽管从命名空间中提取符号名称会更好 - clojure.lang.Named - 而不是依赖于名称空间的(.-name (get ...))表示使用toString

您可能还想添加strclojure.lang.Var类型提示,以避免在您的通话中反映出来。 (如果您希望它们更快,或者您需要clojure.lang.Namespace来调整其他内容以获得性能并希望在此处避免无用的警告。)

如果你希望处理命名空间不存在的可能性(在这种情况下返回*warn-on-reflection*,与通常的Clojure习语保持一致):

nil

或者在Clojure 1.4及更早版本中使用一些(defn fqns ([s] (fqns (.-name *ns*) s)) ([ns s] (some-> ns find-ns .-name ns-aliases (get (symbol (namespace s))) .-name)))