Clojure将var添加到命名空间

时间:2018-05-03 19:22:32

标签: clojure namespaces

如何将var添加到clojure命名空间中,即稍后可以通过调用ns-interns来检索它?

这是(实习ns sym ...),因为实习生创建一个var或重用任何var sym绑定的内容。当其他名称空间需要ns并保持对ns中的变量的引用时,这种区别很重要。我要求的是与ns-unmap相反的。

2 个答案:

答案 0 :(得分:0)

你不能只使用def吗?:

def
Creates and interns or locates a global var with the name of symbol and a
namespace of the value of the current namespace (*ns*). 

并在代码中:

(def alpha)
(def beta :boo)
(intern 'tst.demo.core 'gamma :charlie)

(ns-interns 'tst.demo.core)
    => {alpha  #'tst.demo.core/alpha,  
        beta   #'tst.demo.core/beta
        gamma  #'tst.demo.core/gamma}

我不确定你在这之后会发生什么......?它们看起来都一样。

答案 1 :(得分:0)

背景:ns-interns vs ns-map

ns-interns返回最初在给定命名空间中实现的Vars映射。无法从一个命名空间中获取Var并使其显示在另一个命名空间的ns-interns输出中。因此,如果您想在此处展示Var,则需要使用interndef

相比之下,ns-map是更基本的原语,它返回一个可能更大的地图,包括"自己的实习生",还有通过:require :refer引入的其他命名空间的Vars并导入Java类。

(更为基础是因为ns-interns通过调用ns-map并对其进行过滤来实现,以便只保留最初在给定命名空间中实施的Vars。这是可能的,因为Vars会跟踪它们所在的命名空间创建于(如果有)和任何最初指定的名称。 1

ns-map返回的地图是ns-unmap从中移除映射的地图。请注意,ns-mapns-unmap不区分"自己的Vars"和来自其他命名空间的Vars。当您使用interndef时,以及当映射其他命名空间的Vars时,会创建此映射中的Var条目。如果后者是您想要执行的操作,则有几种方法可以实现它

将Vars从其他命名空间添加到给定的命名空间ns-map

标准方法是在:require :refer … :rename …表单中使用:use :only … :rename …ns或在REPL中使用clojure.core/refer :only … :rename …

user=> (refer 'clojure.string :only '[lower-case] :rename '{lower-case lc})
nil
user=> (lc "ASDF")
"asdf"

NB。 :only之后的参数是非命名空间符号的集合,这些符号将您想要在其自己的命名空间中引入的Vars命名为原始名称,而:rename映射在关键位置具有原始名称以及您在价值位置的替换名称。

如果您乐意接受原始名称,可以省略:rename

也可以调用clojure.core/requireclojure.core/use,这将确保加载命名空间,然后refer您需要的Vars。语法与ns形式相同 - 请参阅下文 - 除了:only:rename之后的符号集合需要在上面的refer调用中引用。

ns形式发言

(:require [clojure.string :refer [lower-case] :rename {lower-case lc}])

(:use [clojure.string :only [lower-case] :rename {lower-case lc}])

:require这些日子往往是首选的。

1 为了完整起见,可以创建不认为自己属于任何命名空间或具有任何特定名称的Vars,但是没有公共API可用于将它们添加到任何命名空间映射中;事实上,他们在命名空间映射中的存在会导致某些奇怪的行为。