为什么Rust会使用显式导入来促进使用语句?

时间:2014-05-23 23:26:21

标签: rust

我看到很多Rust代码,use语句看起来像这样:

use std::io::net::ip::{SocketAddr, Ipv4Addr};

我得到它的方式,这限制了use语句只导入SocketAddrIpv4Addr

从Java或C#等语言的角度来看,这种语言很奇怪,因为import语句总是导入所有公共类型。

我认为使用此语句可以在Rust中使用相同的内容。

use std::io::net::ip::*;

我可以看到显式命名的唯一原因是避免两个不同的导入包含具有相同名称的公共API的冲突。然而,这可以通过别名来解决,所以我想知道是否还有更严格的另一个优点,那就是只需要输入所需的东西"接近?

3 个答案:

答案 0 :(得分:7)

Rust受到Python的启发,它有一个类似的原则:导入都是显式的,虽然支持glob导入(Rust中的use x::*,Python中的from x import *),但它们通常不是推荐使用。

这种理念确实有一些实际影响;例如,调用trait方法只能在trait在范围内时才能完成,因此在导入的traits中存在名称冲突时调用trait方法相当困难(将来使用统一函数调用语法将进行改进) ,您可以拨打Trait::function(self)而不仅仅是self.function())。

但是,大多数情况下,它在Python的禅宗中表达得很好:“显性比隐含更好”。当大量的东西在范围内时,很难看出来自何处的东西,并且对模块结构和/或工具的深入了解变得非常重要;如果一切都是明确的,那么工具很大程度上是不必要的,在简单的文本编辑器中手工处理文件是完全可行的。当然,工具仍然可以提供帮助,但它不是必要的

这就是Rust采用Python明确的导入哲学的原因。

答案 1 :(得分:3)

其中Huon写道

  

它们的某些方面使名称解析大大复杂化   算法(据我所知),无论如何,它们有各种缺点   对于实际代码,例如Python中的等价物令人不悦:   http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#importing

     

也许他们在编译和编译时并不是那么糟糕。静态类型语言?一世   不知道;无论哪种方式,我个人发现代码没有全球导入   更容易阅读,因为我可以找出正在调用的函数   很容易,而glob进口需要更多的努力。

nikomatsakis写道

  

我认为glob进口有它们的位置。例如,在借款中   检查器,有一个浅树的子模块都可以使用   borrowck/mod.rs中定义的数据类型。这似乎相当乏味   愚蠢的要求手动导入所有这些名称,而不是写作   use rustc::middle::borrowck::*。我知道有并发症   但是在分辨率算法中,我会更加顺从   基于那里的基本挑战的论据。

然后转移到RFC 305被steveklabnik拒绝而没有评论他们是否是好风格:

  

Glob进口现在稳定,因此我将结束这一过程。

答案 2 :(得分:0)

全局导入在开发阶段为开发人员提供了便利,一次性导入所有内容,因为在此阶段逐项导入可能很麻烦。它们在专门为此目的设计的 prelude 模块下导出。

完成逻辑后,将 glob 导入替换为显式导入,因为 glob 导入难以追踪,需要额外的努力才能找到来自何处的内容。

它们在 Rust 中被称为通配符导入。

他们不赞成是因为:

  • 会污染命名空间
  • 可能导致冲突并导致混淆错误
  • 与工具相关的宏相关问题

我不认为它与 Python 有任何关系。

弃用通配符的论据有很大的优点,但弃用通配符导入可能不可行,并且会影响开发人员的工作效率,但可以设置剪辑的 lint。

warn-on-all-wildcard-imports: bool:是否允许某些通配符导入(前奏,测试中的超级)。 (默认为 false)。

阅读更多https://rust-lang.github.io/rust-clippy/master/index.html#wildcard_imports