首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么您应该选择:require :refer :all :use in clojure

为什么您应该选择:require :refer :all :use in clojure
EN

Stack Overflow用户
提问于 2014-04-10 08:10:44
回答 5查看 1.3K关注 0票数 6

在他的Clojure样式指南中,作者写道:

代码语言:javascript
复制
Prefer using :require :refer :all over :use in ns macro

他没有解释为什么这是个好主意。是否有充分的理由避免使用:在ns宏中使用?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2014-04-10 09:20:38

我的印像是有两个原因。1)这样做,您更有可能避免任何名称冲突和/或意外遮蔽。2)这种做法提高了代码中使用的函数和变量的最终来源的透明度。第一个非常实用,Chiron的回答提供了一个很好的演示。

第二个比较微妙,但是如果您正在使用大量的库,它可能是非常重要的。假设你是这样的:

代码语言:javascript
复制
(ns your-namespace
  (:use [library-one]
        [library-two]
        [library-three]
        [library-four]
        [library-five]))

然后在代码后面的某个地方调用:

代码语言:javascript
复制
(important-function some-arg some-other-arg)

例如,如果important-function是在library-three中定义的,那么您(或任何试图理解您的代码的人)必须深入研究每个库的代码,以确定它的功能--因为没有任何东西可以指示哪个库是它的源!实际上,如果您有一个REPL可用,您应该能够通过执行以下操作来解决这个问题:

代码语言:javascript
复制
your-namespace> `important-function
> library-three/important-function

但是,这种隐藏的信息可能并不是对那些希望理解您的代码的其他人(包括您未来的自己)施加的最好的东西。另一方面,:required库总是带有前缀。因此,您的代码应该如下所示:

代码语言:javascript
复制
(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。例如:

代码语言:javascript
复制
(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混叠来缩短它。片段示例:

代码语言:javascript
复制
(ns your-namespace
  (:require [library-three :as L3]))

(L3/important-function some-arg some-other-arg)

还请参阅这是如此问题和本指南中关于库和名称空间的内容。

票数 3
EN

Stack Overflow用户

发布于 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这种情况,只要它不是默认的。

票数 6
EN

Stack Overflow用户

发布于 2014-04-11 18:09:55

分离关注点。require允许您加载名称空间,refer允许您定义如何在这些名称空间中引用vars。use使这两个问题更加复杂。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22982303

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档