何时在Clojure/ClojureScript :require中使用别名,何时使用:refer?

3
在Clojure或ClojureScript中使用:require时,何时应该使用别名,何时应该仅选择你使用的函数?
示例:
  1. Using an alias

    (:require [some-package.sub as some])
    
    (some/do-stuff "xyz")
    
  2. Using :refer

    (:require [some-package.sub :refer [do-stuff]])
    
    (do-stuff "xyz")
    
如果依赖项有许多你想使用的函数或你使用所有函数(无论有多少个),使用别名似乎更方便,特别是因为ClojureScript(有意地)不支持:refer :all。另一方面,使用:refer似乎是一种更“干净”的方法,特别是当仅使用该依赖项的某些特定函数时。
选择两者之间的区别时,是否还有其他事情需要考虑(这首先是一个有效的原因)?
我能想到的另一件事是,如果您有大量依赖项和/或在文件中定义了大量自己的函数,则在函数调用中使用别名前缀可能会更有益,即使您仅使用该依赖项提供的一小部分功能。
如何选择使用哪种方法?还是说这是你应该与你的开发团队决定的事情,只要坚持一个方法就可以了?

我认为两者都很不错,因为如果你在代码中看到它们,你可以检查函数来自何处。此外,你的解释非常好,你的考虑非常完美。 - Joaquin
2个回答

6
使用别名可以使任何阅读代码的人立即清楚地知道特定变量的定义位置,特别是在整个项目中标准化使用别名时更容易理解。
未经限定的名称my-fn可能指:
- 在当前命名空间中定义的变量my-fn。 - 在其他命名空间中定义的变量my-fn,通过:require :refer被引入到当前命名空间中并使用了别名。 - 命名为my-fn的本地词法绑定(即函数参数或let绑定变量)。
限定名称a/my-fn只能指:
- 在另一个命名空间中别名为a的变量my-fn(如果你使用单段命名空间,它也可以是命名空间a)。 - 较少见的是,在Java类a中命名为my-fn的静态方法或字段。
限定名称不可能与当前命名空间中定义的任何内容混淆,并且由于您无法在函数参数或let绑定中使用限定名称,因此没有被本地词法绑定遮蔽的风险。使用:require :refer会放弃这种清晰度,而没有给你带来多少回报,我认为应该谨慎使用。

我认为这个详细的解释值得成为被接受的答案,尽管我也觉得levand的回答很有价值,而且可能并没有一个“正确”的答案 - 因为在所提供的选项之间做出选择似乎是一种品味的问题。 - MJV

5

这是主观的,但我几乎完全使用别名。唯一的例外是当我有一个命名空间,从另一个命名空间中使用一个或两个函数很多,以消除噪音。例如,我通常从clojure.test引用deftest。然而,我从不引用超过两个函数。

请注意,您可以同时使用:refer:as

(ns my-ns
   (:require [clojure.test :as test :refer [deftest]]))

我实际上在提问之前尝试过同时使用它们,但是没有看到与仅引用函数有任何区别。但是在你的回答后,我再次尝试了一下,无论是否使用别名前缀,如果我没有搞砸的话,它们都可以工作。这至少在理论上可能是一个好方法,因为人们只能要求他们实际使用的功能,并仍然可以使用别名来更清楚地指出这些功能所在的位置。实际上,我认为这可能会使代码更难阅读,应该只使用别名。 - MJV

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接