【问题标题】:How to find the fully qualified namespace of a symbol?如何找到符号的完全限定名称空间?
【发布时间】:2013-04-18 06:36:13
【问题描述】:

如果我有一个名称空间是别名的符号,例如 q/w,我如何才能找到它的实际名称空间,例如actual.namespace/w?

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

我能做的最好的就是:

 (defn fqns [s] (str (get (ns-aliases *ns*) (symbol (namespace s)))))

肯定有更简单的方法吗?

【问题讨论】:

    标签: clojure namespaces


    【解决方案1】:

    你可以得到一个符号的命名空间对象,如下所示(如果你想把ns的名字作为字符串,那么在最后调用str):

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

    【讨论】:

      【解决方案2】:

      符号本身与任何命名空间对象没有直接联系;它的命名空间部分只是一个内部字符串。只有当它是resolved 时,该字符串才被视为要在其中查找 Var 的实际命名空间的名称。 (特别是,您可以创建符号 foo/bar 而无需创建命名空间 foo 或将 foo 注册为命名空间的别名。)因此,您需要通过 resolve 或自己完成部分工作.

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

      (.. (resolve s) -ns -name)
      

      这会解析一个 Var 对象,然后从其 ns 字段中提取对其命名空间的引用,最后从其 name 字段中提取命名空间的符号名称。 (注意namespacename 函数不起作用,因为变量和命名空间没有实现clojure.lang.Named。)

      问题文本中的函数也很好,尽管最好从命名空间中提取符号名称 -- (.-name (get ...)) -- 而不是通过使用 @ 来依赖命名空间的 toString 表示987654336@.

      您可能还想添加clojure.lang.Varclojure.lang.Namespace 类型提示以避免在您的调用中产生反射。 (如果您希望它们更快,或者如果您需要 *warn-on-reflection* 来调整其他东西以提高性能并希望避免此处出现无用的警告。)

      如果您希望处理命名空间不存在的可能性(并在这种情况下返回 nil,与通常的 Clojure 习惯用法保持一致):

      (defn fqns
        ([s]
          (fqns (.-name *ns*) s))
        ([ns s]
          (some-> ns
                  find-ns
                  .-name
                  ns-aliases
                  (get (symbol (namespace s)))
                  .-name)))
      

      或者在 Clojure 1.4 及更早版本中使用一些 if-lets。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-30
        • 1970-01-01
        • 2019-07-10
        • 1970-01-01
        • 2015-05-17
        • 2017-08-09
        相关资源
        最近更新 更多