Clojure - :refer与:as的区别

7
我正在学习Clojure,其中在使用:require过程中,有一个选项可以使用:refer来引用特定方法或所有方法。
或者使用:as然后选择需要的方法。
我认为我理解了这两个选项之间的区别,并且也看到了文档here,它说:
:as以符号作为其参数,并将该符号作为当前命名空间中库的命名空间的别名。
:refer接受要从命名空间引用的符号列表,或使用关键字:all来带入所有公共vars。
但是我仍然不确定:
1.何时应使用一个选项而不是另一个选项?
2.这两个选项之间是否有性能差异? (我的想法是没有,因为编译器将优化这两个选项)
(我还编写了两个使用core.async的小程序,其中一个使用:as,另一个使用:refer。运行两个程序所需的时间几乎相同。)
1个回答

15

我几乎总是像这样使用:as

(ns demo.core
  (:require
    [clojure.string :as str] ))

(println (str/join ["hello" "there"]))

这样读者可以看到join属于str(一个命名空间别名),并且他们可以轻松地看到join解析为clojure.string/join

考虑替代方案:

(ns demo.core
  (:require
    [clojure.string :refer [join] ))

<snip>
...397 lines of other code...
</snip>

(println (join ["hello" "there"]))

在这里,join 看起来像是在 demo.core 中定义的本地函数,读者可能需要一些时间才能弄清楚它来自哪里。虽然他们可以通过查看 ns 声明来追溯其来源,但除非它是一个非常常见的函数,大多数人都同意在阅读你没有编写的代码时,使用命名空间别名技术更容易/更快地理解。


在执行时,编译器将两种形式都转换为相同的机器码,因此在那方面没有区别。


最好的情况是像 slamhound 这样的工具可以帮助自动引用,但对我来说通常会很麻烦。我建议在项目命名空间上使用 一致的 别名进行引用。这也使得使用简单工具进行重构更容易。 - cfrick
1
参见 Stuart 的 Clojure 命名空间声明风格指南:不要使用 :use,不要使用 :refer :all,不要使用 :rename。仅在非常频繁使用的符号上使用 :require :refer - David Tonhofer

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