Rob*_*lan 31 namespaces clojure keyword
在clojure中,关键字评估自己,例如:
>>:test
:test
Run Code Online (Sandbox Code Playgroud)
它们不接受任何参数,并且它们不受任何限制.那么,为什么我们需要在命名空间中限定关键字?
我知道isa使用derive需要命名空间限定的关键字(例如::test)创建层次结构.是否还有其他需要将关键字放在命名空间中的情况?
Bri*_*per 25
如果任何代码有可能在命名空间的上下文之外与您的关键字进行交互,则应该对命名空间进行命名空间限定.我能想到的主要示例是两个名称空间,它们将键和值放入第三个名称空间中的哈希映射中,其中键是关键字(因为它们通常在Clojure中).一个人为的例子:
user> (ns main)
nil
main> (def DATA (ref {}))
#'main/DATA
main> (ns foo)
nil
foo> (dosync (alter main/DATA assoc :bad 123 ::good 123))
{:foo/good 123, :bad 123}
foo> main/DATA
#<Ref@541b02: {:foo/good 123, :bad 123}>
foo> (ns bar)
nil
bar> (dosync (alter main/DATA assoc :bad 456 ::good 456))
{:bar/good 456, :foo/good 123, :bad 456} ;; oops, no more :bad from foo
Run Code Online (Sandbox Code Playgroud)
你为什么想做这个?好吧,Clojure中的一些核心概念(例如derive,像)以这种方式实现,就像哈希映射一样clojure.core.Multimethods也经常调度关键字值,并且命名空间为另一个命名空间中的多方法定义方法的情况并不少见.不难想象图书馆作者可能想提供类似机制的情况.
如果您的关键字有逃避命名空间的风险,那么对命名空间进行命名空间限定是一个好主意,除非您特别希望关键字能够破坏其他命名空间中的关键字.
Mic*_*zyk 12
Clojure当前需要命名空间限定关键字的一个地方是使用extend函数函数将协议的实现添加到现有类型.(这是1.2功能,可与最新快照一起使用,但不是1.1稳定版本.)相关代码段来自(doc extend):
extend接受一个类型/类(或接口,见下文),以及一个或多个协议+方法映射对.当提供AType作为第一个参数时,它将扩展协议方法的多态性以调用提供的方法.请注意,deftype类型是使用其关键字标签指定的:
:: MyType或:my.ns/MyType
实际上,对于Apple类型和Eatable协议:
(deftype Apple [colour])
(defprotocol Eatable (eat [x]))
Run Code Online (Sandbox Code Playgroud)
抛出异常(No implementation of method: :eat等):
(extend :Apple Eatable {:eat (fn [x] (println (str (name (:colour x)) ", yummy!")))})
(eat (Apple :red))
Run Code Online (Sandbox Code Playgroud)
打印出来red, yummy!:
(extend ::Apple Eatable {:eat (fn [x] (println (str (name (:colour x)) ", yummy!")))})
(eat (Apple :red))
Run Code Online (Sandbox Code Playgroud)
注意我刚刚在REPL中输入了所有内容.另请注意,如果要重现它,最好按上面给出的顺序键入/粘贴它; 例如,重新评估其中任何一个(deftype Apple [colour])和(defprotocol Eatable (eat [x]))表单(甚至两者)都不会使Clojure忘记协议实现.
同样,这是一个1.2特性,因此它甚至不存在于1.1中,并且可能在实际发布1.2之前发生变化.
Brian说,在多个名称空间之间共享哈希映射是另一个可能的用例.请注意,不需要涉及引用类型.假设有一堆库 - 可能会在将来添加 - 操纵(可能转换,也许只是观察)由关键字键控的哈希映射,其中每个库可以自由定义它查找的关键字和什么它用它们; 然后人们可能会试图使用命名空间限定的关键字来避免冲突.
实际上,目前存在一个完全没有设计的例子,即Ring spec v0.1(当今Clojure Web生态系统的关键部分).请参阅Ring Google小组(由Ring作者
Mark McGranaghan制作)的请求和响应地图关键字命名空间消息,以
了解该设计决策背后的基本原理,以及决定不再需要Ring spec v0中的命名空间关键字. 2.James Reeves(Compojure的作者)也支持这一变化.
最终,作为所有命名空间,这是一个避免碰撞的功能.如今编写的Clojure代码并不倾向于关注"私有"关键字,因此它们没有太多用处; 但是当它们可能有所作为时,将它们提供是很好的.