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>());
});
}
}
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).
using System;
in C# is totally normal and in Java, you even don't need to write import java.lang.*;
as it is already imported by default. And I don't see any flaw in writing multiple statements - if you need to call something with the same name, you can always call identifiers with their full name, as you did in your second code example.
P.S.: Sorry for writing an opinion driven answer^^