在他的Clojure样式指南中,作者写道:
Prefer using :require :refer :all over :use in ns macro他没有解释为什么这是个好主意。是否有充分的理由避免使用:在ns宏中使用?
发布于 2014-04-10 09:20:38
我的印像是有两个原因。1)这样做,您更有可能避免任何名称冲突和/或意外遮蔽。2)这种做法提高了代码中使用的函数和变量的最终来源的透明度。第一个非常实用,Chiron的回答提供了一个很好的演示。
第二个比较微妙,但是如果您正在使用大量的库,它可能是非常重要的。假设你是这样的:
(ns your-namespace
(:use [library-one]
[library-two]
[library-three]
[library-four]
[library-five]))然后在代码后面的某个地方调用:
(important-function some-arg some-other-arg)例如,如果important-function是在library-three中定义的,那么您(或任何试图理解您的代码的人)必须深入研究每个库的代码,以确定它的功能--因为没有任何东西可以指示哪个库是它的源!实际上,如果您有一个REPL可用,您应该能够通过执行以下操作来解决这个问题:
your-namespace> `important-function
> library-three/important-function但是,这种隐藏的信息可能并不是对那些希望理解您的代码的其他人(包括您未来的自己)施加的最好的东西。另一方面,:required库总是带有前缀。因此,您的代码应该如下所示:
(ns your-namespace
(:require [library-one]
[library-two]
[library-three]
[library-four]
[library-five]))
...
(library-three/important-function some arg some-other-arg)这使得定义important-function的位置变得非常清楚。注意,这应该等同于指定:refer :all。尽管:refer :all可以向其他人指出,您专门考虑了要引用哪些vars,并做出了包含库中所有这些vars的有意识的决定。
如果你不担心名字clashing...well,你可能应该担心。但是,如果您仍然没有这样做,并且您希望清楚vars的来源,那么您总是可以使用:use来使用:only。例如:
(ns your-namespace
(:use [library-one :only []]
[library-two :only []]
[library-three :only [important-function]]
[library-four :only []]
[library-five :only []]))
...
(important-function some arg some-other-arg)显然,如果您是带有空白:use向量的:only库,那么您最好一开始就不使用:use,我只是想与前面的示例结合起来。执行:require可能看起来很冗长,但是您可以通过与:as混叠来缩短它。片段示例:
(ns your-namespace
(:require [library-three :as L3]))
(L3/important-function some-arg some-other-arg)还请参阅这是如此问题和本指南中关于库和名称空间的内容。
发布于 2014-04-10 10:46:43
我建议你看看原创讨论,它导致了这个规则。核心原理可以找到这里。我将在这里包括讨论的开始:
以前曾讨论过ns宏的复杂性。特别是:使用导致默认情况下所有var被引用这一事实被广泛认为是不幸的,使用和要求之间的区别是语言新手概念开销的一个来源。我们不能改变这样的事实:默认情况下,use指的是所有的东西,而不破坏大量的现有代码。但是它可以增强:要求支持引用指定的vars,让我们可以放弃或以其他方式阻止使用:use。 而不是这种形式: (ns mork.test (:使用[mork.stats :只汇总-组] mork.utils :只有[条解析-fn])(:要求mork.view :as view cheshire.core :as json) (:import (java.io PushbackReader)) 我们可以用这个: (ns mork.test (:mork.stats :refer [mork.stats -group] mork.utils :refer [strip ] mork.view :as view cheshire.core :as json) (:import (java.io PushbackReader)) 在以前的线程中已经达成了这样的共识:将:import作为一个与:require不同的概念是可取的,我同意我们不应该将Clojure和Java类混为一谈。 在引用名称空间中的所有vars是可以接受的情况下(特别是在编写测试名称空间时,引入所有被测试的clojure.test和名称空间似乎是合理的),因此我们可能应该支持:refer :all for这种情况,只要它不是默认的。
发布于 2014-04-11 18:09:55
分离关注点。require允许您加载名称空间,refer允许您定义如何在这些名称空间中引用vars。use使这两个问题更加复杂。
https://stackoverflow.com/questions/22982303
复制相似问题