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>());
});
}
}
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.
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.
No, C does not have a namespace mechanism whereby you can provide “module-like data hiding”.
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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With