Why does Rust allow multidefinition of identifiers? - rust

Consider a mini example
fn main() {
let a = Vec::from([1, 2, 3]);
let Vec = 1.;
println!("{}", Vec);
let b = Vec::from([1, 2, 3]);
let c: Vec<i32> = Vec::new();
}
where I redefine Vec as a f64 variable. Why does Rust allow for such operation?
The code above will print 1. and suprisingly after redefining Vec as a number, the lines let b = Vec::new(); work as well! So Vec exists both as an f64 and a Vec struct? In many other languages, I think they will throw errors.
Suppose that both f64 and Vec have a method test() implemented, if I call Vec.test(), does it excute test() from f64 or Vec?

Types and variables are distinguished by syntax, so using the same identifier for both is harmless and therefore allowed. While that's slightly unusual, it's not unheard of - for example, this is valid Java:
public class HelloWorld {
public static void main(String []args) {
int hello = 1;
hello(hello); // <-- wat
}
static void hello(int n) {
System.out.println("Hello " + n);
}
}
Note that such use of identifier will inevitably trigger a compilation warning because variables and types use different case conventions.
Suppose that both f64 and Vec have a method test() implemented, if I call Vec.test(), does it execute test() from f64 or Vec?
It executes the one from f64.
There is no ambiguity because Vec as type and Vec as value of type f64 are completely different things. To call the method defined by the Vec type through the Vec type, you'd have to call Vec::test(...). To call the f64 method through the Vec variable you'd have to call Vec.test(...) or f64::test(&Vec, ...) - no ambiguity either way. (And that's assuming f64::test() takes &self; if it didn't, you couldn't invoke it through instance in the first place, so there'd be even less confusion.)

Related

in rust-lang, what's the difference between `static_fly::<Number>(number);` and `static_fly(number);`

in rust-lang, what's the difference between static_fly::<Number>(number); and static_fly(number);
here is a demo:
enum Number {
Zero,
One,
Two,
}
trait Fly {
fn fly(&self);
}
impl Fly for Number {
fn fly(&self) {
println!("flying number: {}", self)
}
}
// 静态分发
fn static_fly<T: Fly>(f: T){
print!("静态分发\t");
f.fly()
}
fn main() {
let number = Zero;
// 泛型的分发调用
static_fly(number); // <-- here is the 1st method for calling static_fly
// static_fly::<Number>(number); // <-- here is the 2nd method for calling static_fly
}
what's the difference between this two calling.
The two methods of calling the function are equivalent in this case.
Given enough information, Rust can infer generic type arguments. In the case of static_fly(number) the compiler has inferred that T is Number. In the case of static_fly::<Number>(number) you are just providing the type for the type argument T explicitly.
This is very similar to other kinds of inference the compiler performs. For example, both of these statements are also equivalent:
let number = Zero;
let number: Number = Zero;
It's the same principle -- in one case we specify the type, in the other we let the compiler figure it out.
Its the same thing as let a = b; compared to let a: Type = b;. It gives you the option to explicitly state which type is used in an operation. Normally Rust can infer what you want to do, however if there is any ambiguity the compiler will ask you to explicitly specify a type.
For example, the most common instance of this I run into is when calling .collect() on an iterator.
fn foo(vals: &[u32]) -> Vec<u32> {
// In this case there is no ambiguity since the result of collect must
// be a `Vec<u32>`. Since the compiler can infer the type, we don't need
// to state what type collect uses.
vals.iter()
.map(|x| x * 2)
.collect()
}
fn bar(vals: &[u32]) -> u32 {
// In this case the compiler is unable to infer a type as collect can
// create any type that can be initialized with an iterator.
let mut a = vals.iter()
.map(|x| x * 2)
.collect();
a.sort();
a[0]
}
For this example there are a couple ways you can fix bar.
// State the type of a so the compiler can infer collect's types
let mut a: Vec<u32> = vals.iter()
.map(|x| x * 2)
.collect();
// State the types used by the function in question but let the compiler infer a's type
let mut a = vals.iter()
.map(|x| x * 2)
.collect::<Vec<u32>>();
Another option is to only partially state the type in question. A type name can be replaced with an underscore to tell the compiler to infer that part of a type. This is generally my preferred way of handling this specific case.
// Tell the compiler we will collect items to a Vec, but let it infer the content type
let mut a = vals.iter()
.map(|x| x * 2)
.collect::<Vec<_>>();

how to properly distinguish borrow and move? [duplicate]

What is the purpose of & in the code &i in list? If I remove the &, it produces an error in largest = i, since they have mismatched types (where i is &32 and i is i32). But how does &i convert i into i32?
fn largest(list: &[i32]) -> i32 {
println!("{:?}", list);
let mut largest = list[0];
for &i in list {
if i > largest {
largest = i;
}
}
largest
}
fn main() {
let hey = vec![1, 3, 2, 6, 90, 67, 788, 12, 34, 54, 32];
println!("The largest number is: {}", largest(&hey));
}
Playground
It seems like it is somehow dereferencing, but then why in the below code, is it not working?
fn main() {
let mut hey: i32 = 32;
let x: i32 = 2;
hey = &&x;
}
It says:
4 | hey = &&x;
| ^^^ expected i32, found &&i32
|
= note: expected type `i32`
found type `&&i32`
So normally when you use for i in list, the loop variable i would be of type &i32.
But when instead you use for &i in list, you are not dereferencing anything, but instead you are using pattern matching to explicitly destructure the reference and that will make i just be of type i32.
See the Rust docs about the for-loop loop variable being a pattern and the reference pattern that we are using here. See also the Rust By Example chapter on destructuring pointers.
An other way to solve this, would be to just keep i as it is and then comparing i to a reference to largest, and then dereferencing i before assigning to largest:
fn largest(list: &[i32]) -> i32 {
println!("{:?}", list);
let mut largest = list[0];
for i in list {
if i > &largest {
largest = *i;
}
}
largest
}
fn main() {
let mut hey: i32 = 32;
let x: i32 = 2;
hey = &&x;
}
This simply doesn't work, because here you are assigning hey, which is an i32, to a reference to a reference to an i32. This is quite unrelated to the pattern matching and destructuring in the loop variable case.
This is the effect of destructuring. I won't completely describe that feature here, but in short:
In many syntax contexts (let bindings, for loops, function arguments, ...) , Rust expects a "pattern". This pattern can be a simple variable name, but it can also contain some "destructuring elements", like &. Rust will then bind a value to this pattern. A simple example would be something like this:
let (a, b) = ('x', true);
On the right hand side there is a value of type (char, bool) (a tuple). This value is bound to the left hand pattern ((a, b)). As there is already a "structure" defined in the pattern (specifically, the tuple), that structure is removed and a und b bind to the tuple's elements. Thus, the type of a is char and the type of b is bool.
This works with a couple of structures, including arrays:
let [x] = [true];
Again, on the right side we have a value of type [bool; 1] (an array) and on the left side we have a pattern in the form of an array. The single array element is bound to x, meaning that the type of x is bool and not [bool; 1]!
And unsurprisingly, this also works for references!
let foo = 0u32;
let r = &foo;
let &c = &foo;
Here, foo has the type u32 and consequently, the expression &foo has the type &u32. The type of r is also &u32, as it is a simple let binding. The type of c is u32 however! That is because the "reference was destructured/removed" by the pattern.
A common misunderstanding is that syntax in patterns has exactly the opposite effect of what the same syntax would have in expressions! If you have a variable a of type [T; 1], then the expression [a] has the type [[T; 1]; 1] → it adds stuff. However, if you bind a to the pattern [c], then y has the type T → it removes stuff.
let a = [true]; // type of `a`: `[bool; 1]`
let b = [a]; // type of `b`: `[[bool; 1]; 1]`
let [c] = a; // type of `c`: `bool`
This also explains your question:
It seems like it is somehow dereferencing, but then why in the below code, it is not working?
fn main() {
let mut hey:i32 = 32;
let x:i32 = 2;
hey = &&x;
}
Because you use & on the expression side, where it adds a layer of references.
So finally about your loop: when iterating over a slice (as you do here), the iterator yields reference to the slice's elements. So in the case for i in list {}, i has the type &i32. But the assignment largest = i; requires a i32 on the right hand side. You can achieve this in two ways: either dereference i via the dereference operator * (i.e. largest = *i;) or destructure the reference in the loop pattern (i.e. for &i in list {}).
Related questions:
Iterating over a slice's values instead of references in Rust?
Why is & needed to destructure a list of tuples during iteration?

What is the purpose of `&` before the loop variable?

What is the purpose of & in the code &i in list? If I remove the &, it produces an error in largest = i, since they have mismatched types (where i is &32 and i is i32). But how does &i convert i into i32?
fn largest(list: &[i32]) -> i32 {
println!("{:?}", list);
let mut largest = list[0];
for &i in list {
if i > largest {
largest = i;
}
}
largest
}
fn main() {
let hey = vec![1, 3, 2, 6, 90, 67, 788, 12, 34, 54, 32];
println!("The largest number is: {}", largest(&hey));
}
Playground
It seems like it is somehow dereferencing, but then why in the below code, is it not working?
fn main() {
let mut hey: i32 = 32;
let x: i32 = 2;
hey = &&x;
}
It says:
4 | hey = &&x;
| ^^^ expected i32, found &&i32
|
= note: expected type `i32`
found type `&&i32`
So normally when you use for i in list, the loop variable i would be of type &i32.
But when instead you use for &i in list, you are not dereferencing anything, but instead you are using pattern matching to explicitly destructure the reference and that will make i just be of type i32.
See the Rust docs about the for-loop loop variable being a pattern and the reference pattern that we are using here. See also the Rust By Example chapter on destructuring pointers.
An other way to solve this, would be to just keep i as it is and then comparing i to a reference to largest, and then dereferencing i before assigning to largest:
fn largest(list: &[i32]) -> i32 {
println!("{:?}", list);
let mut largest = list[0];
for i in list {
if i > &largest {
largest = *i;
}
}
largest
}
fn main() {
let mut hey: i32 = 32;
let x: i32 = 2;
hey = &&x;
}
This simply doesn't work, because here you are assigning hey, which is an i32, to a reference to a reference to an i32. This is quite unrelated to the pattern matching and destructuring in the loop variable case.
This is the effect of destructuring. I won't completely describe that feature here, but in short:
In many syntax contexts (let bindings, for loops, function arguments, ...) , Rust expects a "pattern". This pattern can be a simple variable name, but it can also contain some "destructuring elements", like &. Rust will then bind a value to this pattern. A simple example would be something like this:
let (a, b) = ('x', true);
On the right hand side there is a value of type (char, bool) (a tuple). This value is bound to the left hand pattern ((a, b)). As there is already a "structure" defined in the pattern (specifically, the tuple), that structure is removed and a und b bind to the tuple's elements. Thus, the type of a is char and the type of b is bool.
This works with a couple of structures, including arrays:
let [x] = [true];
Again, on the right side we have a value of type [bool; 1] (an array) and on the left side we have a pattern in the form of an array. The single array element is bound to x, meaning that the type of x is bool and not [bool; 1]!
And unsurprisingly, this also works for references!
let foo = 0u32;
let r = &foo;
let &c = &foo;
Here, foo has the type u32 and consequently, the expression &foo has the type &u32. The type of r is also &u32, as it is a simple let binding. The type of c is u32 however! That is because the "reference was destructured/removed" by the pattern.
A common misunderstanding is that syntax in patterns has exactly the opposite effect of what the same syntax would have in expressions! If you have a variable a of type [T; 1], then the expression [a] has the type [[T; 1]; 1] → it adds stuff. However, if you bind a to the pattern [c], then y has the type T → it removes stuff.
let a = [true]; // type of `a`: `[bool; 1]`
let b = [a]; // type of `b`: `[[bool; 1]; 1]`
let [c] = a; // type of `c`: `bool`
This also explains your question:
It seems like it is somehow dereferencing, but then why in the below code, it is not working?
fn main() {
let mut hey:i32 = 32;
let x:i32 = 2;
hey = &&x;
}
Because you use & on the expression side, where it adds a layer of references.
So finally about your loop: when iterating over a slice (as you do here), the iterator yields reference to the slice's elements. So in the case for i in list {}, i has the type &i32. But the assignment largest = i; requires a i32 on the right hand side. You can achieve this in two ways: either dereference i via the dereference operator * (i.e. largest = *i;) or destructure the reference in the loop pattern (i.e. for &i in list {}).
Related questions:
Iterating over a slice's values instead of references in Rust?
Why is & needed to destructure a list of tuples during iteration?

What do I have to do to solve a "use of moved value" error?

I'm trying to compute the 10,001st prime in Rust (Project Euler 7), and as a part of this, my method to check whether or not an integer is prime references a vector:
fn main() {
let mut count: u32 = 1;
let mut num: u64 = 1;
let mut primes: Vec<u64> = Vec::new();
primes.push(2);
while count < 10001 {
num += 2;
if vectorIsPrime(num, primes) {
count += 1;
primes.push(num);
}
}
}
fn vectorIsPrime(num: u64, p: Vec<u64>) -> bool {
for i in p {
if num > i && num % i != 0 {
return false;
}
}
true
}
When I try to reference the vector, I get the following error:
error[E0382]: use of moved value: `primes`
--> src/main.rs:9:31
|
9 | if vectorIsPrime(num, primes) {
| ^^^^^^ value moved here, in previous iteration of loop
|
= note: move occurs because `primes` has type `std::vec::Vec<u64>`, which does not implement the `Copy` trait
What do I have to do to primes in order to be able to access it within the vectorIsPrime function?
With the current definition of your function vectorIsPrime(), the function specifies that it requires ownership of the parameter because you pass it by value.
When a function requires a parameter by value, the compiler will check if the value can be copied by checking if it implements the trait Copy.
If it does, the value is copied (with a memcpy) and given to the function, and you can still continue to use your original value.
If it doesn't, then the value is moved to the given function, and the caller cannot use it afterwards
That is the meaning of the error message you have.
However, most functions do not require ownership of the parameters: they can work on "borrowed references", which means they do not actually own the value (and cannot for example put it in a container or destroy it).
fn main() {
let mut count: u32 = 1;
let mut num: u64 = 1;
let mut primes: Vec<u64> = Vec::new();
primes.push(2);
while count < 10001 {
num += 2;
if vector_is_prime(num, &primes) {
count += 1;
primes.push(num);
}
}
}
fn vector_is_prime(num: u64, p: &[u64]) -> bool {
for &i in p {
if num > i && num % i != 0 {
return false;
}
}
true
}
The function vector_is_prime() now specifies that it only needs a slice, i.e. a borrowed pointer to an array (including its size) that you can obtain from a vector using the borrow operator &.
For more information about ownership, I invite you to read the part of the book dealing with ownership.
Rust is, as I would say, a “value-oriented” language. This means that if you define primes like this
let primes: Vec<u64> = …
it is not a reference to a vector. It is practically a variable that stores a value of type Vec<u64> just like any u64 variable stores a u64 value. This means that if you pass it to a function defined like this
fn vec_is_prime(num: u64, vec: Vec<u64>) -> bool { … }
the function will get its own u64 value and its own Vec<u64> value.
The difference between u64 and Vec<u64> however is that a u64 value can be easily copied to another place while a Vec<u64> value can only move to another place easily. If you want to give the vec_is_prime function its own Vec<u64> value while keeping one for yourself in main, you have to duplicate it, somehow. That's what's clone() is for. The reason you have to be explicit here is because this operation is not cheap. That's one nice thing about Rust: It's not hard to spot expensive operations. So, you could call the function like this
if vec_is_prime(num, primes.clone()) { …
but that's not really what you want, actually. The function does not need its own a Vec<64> value. It just needs to borrow it for a short while. Borrowing is much more efficient and applicable in this case:
fn vec_is_prime(num: u64, vec: &Vec<u64>) -> bool { …
Invoking it now requires the “borrowing operator”:
if vec_is_prime(num, &primes) { …
Much better. But we can still improve it. If a function wants to borrow a Vec<T> just for the purpose of reading it, it's better to take a &[T] instead:
fn vec_is_prime(num: u64, vec: &[u64]) -> bool { …
It's just more general. Now, you can lend a certain portion of a Vec to the function or something else entirely (not necessarily a Vec, as long as this something stores its values consecutively in memory, like a static lookup table). What's also nice is that due to coersion rules you don't need to alter anything at the call site. You can still call this function with &primes as argument.
For String and &str the situation is the same. String is for storing string values in the sense that a variable of this type owns that value. &str is for borrowing them.
You move value of primes to the function vectorIsPrime (BTW Rust use snake_case by convention). You have other options, but the best one is to borrow vector instead of moving it:
fn vector_is_prime(num: u64, p: &Vec<u64>) -> bool { … }
And then passing reference to it:
vector_is_prime(num, &primes)

Why does the binary + operator not work with two &mut int?

fn increment(number: &mut int) {
// this fails with: binary operation `+` cannot be applied to type `&mut int`
//let foo = number + number;
let foo = number.add(number);
println!("{}", foo);
}
fn main() {
let mut test = 5;
increment(&mut test);
println!("{}", test);
}
Why does number + number fail but number.add(number) works?
As a bonus question: The above prints out
10
5
Am I right to assume that test is still 5 because the data is copied over to increment? The only way that the original test variable could be mutated by the increment function would be if it was send as Box<int>, right?
number + number fails because they're two references, not two ints. The compiler also tells us why: the + operator isn't implemented for the type &mut int.
You have to dereference with the dereference operator * to get at the int. This would work let sum = *number + *number;
number.add(number); works because the signature of add is fn add(&self, &int) -> int;
Am I right to assume that test is still 5 because the data is copied
over to increment? The only way that the original test variable could
be mutated by the increment function would be if it was send as
Box, right?
Test is not copied over, but is still 5 because it's never actually mutated. You could mutate it in the increment function if you wanted.
PS: to mutate it
fn increment(number: &mut int) {
*number = *number + *number;
println!("{}", number);
}

Resources