【问题标题】:Rust "use" vs. C++ "using namespace"Rust“使用”与 C++“使用命名空间”
【发布时间】:2015-05-14 20:04:15
【问题描述】:

在 Rust 中声明多个“使用”语句是否被认为是不好的风格?我是一名最近开始尝试 Rust 的 C++ 程序员。我在查看 Rust 代码时注意到的一件事是,在许多 Rust 程序中,程序顶部会有一堆 use 语句。来自 C++,不鼓励使用 using namespace std,尤其是在制作头文件时,但在我见过的大多数 Rust 程序中似乎并非如此。那么以下哪些琐碎的例子被认为是更好的 Rust 编程风格?如果您正在制作二进制程序与模块,它会改变吗?为什么?

use std::sync::Arc;
use std::sync::Mutex;
use std::thread::Thread;
use std::rand::random;

fn main() {
    let mut vec: Vec<char> = (0u8..10).map(|i| i as char).collect();

    let mut data = Arc::new(Mutex::new(vec));
    for i in 1usize..10 {
        let data = data.clone();
        let thread = Thread::spawn(move || {
            let mut data = match data.lock() {
                Ok(guard)   => guard,
                Err(e)      => panic!("{}, was poisoned", e)
            };
            data.push(random::<char>());
        });
    }
}

或者这个……

fn main() {
    let mut vec: Vec<char> = (0u8..10).map(|i| i as char).collect();

    let mut data = std::sync::Arc::new(
                            std::sync::Mutex::new(vec)
                                        );
    for i in 1usize..10 {
        let data = data.clone();
        let thread = std::thread::Thread::spawn(move || {
            let mut data = match data.lock() {
                Ok(guard)   => guard,
                Err(e)      => panic!("{}, was poisoned", e)
            };
            data.push(std::rand::random::<char>());
        });
    }
}

【问题讨论】:

    标签: namespaces rust std using


    【解决方案1】:

    您可能对外观相似的名称(useusing namespace)感到困惑。事实上,它们在语义上非常不同。

    C++ 中的using namespace 将命名空间的全部内容包含在当前作用域中,因此,例如,您可以使用cout 而不是std::cout

    using namespace std;
    
    cout << "Hello!\n";
    

    然而,Rust 中的use 仅包含指定的名称,因此您仍然需要限定您实际指的是哪个项目:

    use std::mem;
    use std::fmt::Debug;
    
    fn do_something<T: Debug>(t: T) { ... }
    
    fn main() {
        let (mut x, mut y) = ...;
        mem::swap(&mut x, &mut y);
    }
    

    注意Debug 是如何在没有限定符的情况下使用的,但swap 仍然需要模块限定符,因此Rust 中的use 更像是C++ 中的using(没有namespace)。因为use 的导入非常具体,所以几乎总是使用它被认为是一种很好的风格,所以你的第一个例子是惯用的。

    事实上,using namespace 更像是 Rust 中的 glob 导入:

    use std::*;
    

    而且确实有点不鼓励全局导入。然而,Rust 结构约定比 C++ 使用的更灵活(特别是在 std 库中),所以use std::* 不会给你整个标准库,只有顶层模块。 Glob 导入在其他几种情况下也很有用,例如当从另一个模块重新导出名称或在一个模块中组装所有库扩展特征时。

    不,无论您是在编写库还是可执行文件,约定都不会改变。 Rust 没有像 C/C++ 的头文件那样包含文字,因此每个编译单元都是完全独立的,并且可以有任何你喜欢的导入——它不会影响它的用户(当然,除非这些是 pub use 的)。

    【讨论】:

    • 请注意,C++ 也有单一名称 using,例如using std::cout; 在 C++ 中工作得很好。所以不,using 不是全局导入语句。另一方面,using namespace 是,它的效果是不言自明的。
    • 啊,对不起,你是对的。我不太会使用 C++,所以我肯定会弄错。
    【解决方案2】:

    using System; 在 C# 中是完全正常的,而在 Java 中,您甚至不需要编写 import java.lang.*;,因为它已经默认导入。而且我看不出编写多个语句有任何缺陷——如果你需要调用同名的东西,你总是可以用它们的全名调用标识符,就像你在第二个代码示例中所做的那样。

    P.S.:很抱歉写了一个意见驱动的答案^^

    【讨论】:

      猜你喜欢
      • 2014-07-17
      • 1970-01-01
      • 2011-10-01
      • 1970-01-01
      • 2011-07-15
      • 1970-01-01
      • 2012-01-18
      • 2011-05-05
      • 2011-03-13
      相关资源
      最近更新 更多