Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rust "use" vs. C++ "using namespace"

Is it considered bad style to declare multiple "use" statements in Rust? I am a C++ programmer that recently began trying out Rust. One thing I've noticed as I review Rust code is that in many Rust programs there will be a bunch of use statements at the top of the program. Coming from C++, it was discouraged to use using namespace std especially when making header files, but that doesn't seem to be the case in most of the Rust programs I've seen. So which of the following trivial examples is considered to be better Rust programming style? Does it change if you're making a binary program vs. a module? And why?

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>());
        });
    }
}

Or this...

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>());
        });
    }
}
like image 364
Daniel Robertson Avatar asked Mar 12 '15 15:03

Daniel Robertson


People also ask

Is it good practice to use namespace?

The statement using namespace std is generally considered bad practice. The alternative to this statement is to specify the namespace to which the identifier belongs using the scope operator(::) each time we declare a type.

Are there namespaces in Rust?

Namespaces contain all the names (called identifiers) in Rust code. This does not include keywords, but it includes the names of local variables, types, traits, functions, modules, generic arguments, macros, and so on.

Does C have using namespace?

No, C does not have a namespace mechanism whereby you can provide “module-like data hiding”.

What is the benefits of using namespace?

The biggest advantage of using namespace is that the class names which are declared in one namespace will not clash with the same class names declared in another namespace. It is also referred as named group of classes having common features.


1 Answers

You are probably confused by the similarly looked names (use and using namespace). In fact they are very different in semantics.

using namespace in C++ includes the whole contents of a namespace into the current scope, so, for example, you can use cout instead of std::cout:

using namespace std;

cout << "Hello!\n";

use in Rust, however, includes only the specified name, so you still have to qualify which item you are actually referring to:

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);
}

Note how Debug is used without qualifiers but swap still requires a module qualifier, so use in Rust is more like using (without namespace) in C++. Because use is very specific in what it imports, it is considered a good style to use it almost always, so your first example is the idiomatic one.

In fact, using namespace is more like glob imports in Rust:

use std::*;

And glob imports indeed are somewhat discouraged. However, Rust structuring conventions are more flexible that the ones used by C++ (in particular, in the std library), so use std::* won't give you the whole standard library, only the top-level modules. Glob imports are also useful in a couple of other situations, e.g. when reexporing names from another module or assembling all library extension traits in one module.

And no, conventions do not change regardless of if you're writing a library or an executable. Rust does not have anything like C/C++'s headers with literal inclusions, so each compilation unit is completely independent and can have any imports you like - it won't affect its users (unless these are pub use's, of course).

like image 132
Vladimir Matveev Avatar answered Sep 28 '22 11:09

Vladimir Matveev