Following the example in the Rust book using its suggested rand = "0.6.0"
, I get code that looks like this:
use rand::Rng;
fn main() {
let secret_number = rand::thread_rng().gen_range(1, 101);
println!("The secret number is: {}", secret_number);
}
Everything the book says later on in its chapter on modules suggests that if you do a use rand::Rng;
as above, you'll be able to use Rng
. If that happens to be a module itself, you can use submodules with Rng::submodule
. If that happens to be a type, you just use it as Rng
. In the code above however, we never use Rng
anywhere.
Instead, we use the seemingly unrelated rand::thread_rng()
. From what I understand, since rand
is the name of the top level crate, we should be able to use it, even without the use
statement that doesn't appear to do anything.
Instead, for some reason, the program will fail to compile without the use
statement. This is really confusing. I wish the book did a better job explaining what was happening there.
Why do we need the use statement? Why are we not using Rng
? How is it related to rand::thread_rng()
?
I come from a Python background, so I'm used to the idea that if you import threading
, you're using threading.something
. If you import django.utils
, you're using django.utils.something
. This seems like an import of django.utils
where you're using the totally unrelated django.urls
.
You cannot call trait methods unless the trait is in scope.
In the code above however, we never use
Rng
anywhere.
You're using Rng
. gen_range()
is a trait method defined by the Rng
trait so Rng
must be in scope for you to call gen_range()
.
The nitty gritty details: rand::thread_rng()
returns ThreadRng
which implements RngCore
and gets an Rng
implementation because of the generic blanket impl impl<R> Rng for R where R: RngCore + ?Sized
.