All I wanna do is to swap the first and the last element in Vec. So I wrote this:
// getting a vector of integers from stdin:
let mut ranks = std::io::stdin()
.lock()
.lines()
.next()
.unwrap()
.unwrap()
.trim()
.split_whitespace()
.map(|s| s.parse::<usize>().unwrap())
.collect::<Vec<usize>>();
// ...
// pushing something to ranks
// ...
ranks.swap(0, ranks.len() - 1); // <------ TRYING TO SWAP
And of course, it doesn't work, because
error[E0502]: cannot borrow `ranks` as immutable because it is also borrowed as mutable
--> src\main.rs:4:19
|
4 | ranks.swap(0, ranks.len() - 1);
| --------------^^^^^^^^^^^-----
| | | |
| | | immutable borrow occurs here
| | mutable borrow later used by call
| mutable borrow occurs here
|
help: try adding a local storing this argument...
--> src\main.rs:4:19
|
4 | ranks.swap(0, ranks.len() - 1);
| ^^^^^^^^^^^
help: ...and then using that local as the argument to this call
By using this piece of advice the compiler gave me, I came up with following:
let last = ranks.len() - 1;
ranks.swap(0, last);
...which looks terrible.
So the thing is: why do I need to create local variable to store vector length, if I want to pass it to the method? Well, of course because of the borrowing rules: the value of ranks
will be borrowed as mutable as I call swap
, so that I can't use ranks.len()
anymore.
But isn't it reasonable to suppose that the values of parameters will be calculated before the method starts to do anything and before it somehow can change the content of vector or it's length?
Basically, the order of computing parameters of a function is straight in Rust, which creates many obsticles for writing clean code for me. So I would like to ask, why the order is chosen to be straight? Cause if it was reverse, things would be much easier to express. For instance, the above piece of code could be rewritten as:
ranks.swap(0, ranks.len() - 1);
...which (I think you would agree) is much more readable and cleaner.
Also, it is strange that the similar in the sense of borrowing code compiles succesfully:
let mut vec = vec![1, 2, 3]; // creating vector
vec.push(*vec.last().unwrap()); // DOUBLE BORROWING HERE!!!
// ^ ^
// | |
// | ----- immutable
// ----- mutable
println!("{:?}", vec);
So what the hell is going on? Double standarts, aren't they? I would like to know the answer. Thank you for explanation.