This question already has answers here:
Does Rust free up the memory of overwritten variables?
(3 answers)
When does Rust drop the value in case of reassignment? [duplicate]
(1 answer)
Closed 15 days ago.
Here are two examples of dynamic mutable value.
pub fn main() {
let mut x = String::from("Hello");
println!("{}", x);
x = format!("{x}, world!");
println!("{}", x);
}
So as you can see, we have a mutable variable x. x gets borrowed by format! & turns to a new value that is then assigned back to x.
pub fn main() {
let mut x = String::from("Hello, world!");
println!("{}", x);
x = String::from("Lorem, ipsum!");
println!("{}", x);
}
My real problem is this code, where the value assigned to x has no connection with it's initial value. Variables can only take owner-ship over a single value, so how does Rust keep track of "Hello, world!" & "Lorem, ipsum!"? Exactly what happens to mutable values after assignments?
My guess is that it checks if the value getting assigned to depends on the first one, if yes, it won't drop it.
This question already has answers here:
How to get mutable references to two array elements at the same time?
(8 answers)
Closed 8 months ago.
I'm solving a problem from Leetcode and encountered the fact that Rust won't let me execute it efficiently. What am I doing wrong? I know about the book article about references and borrowing and would like to know how to solve this problem despite the peculiarities of the language.
I am trying to create one reference for a vec that should change and another for a vec that will not change. Rust won't let me do that. The program works, but only when using .clone(), which will be very slow and not necessary (last_row does not change anywhere, only the values are derived from there).
Here is the working code:
use std::cmp;
fn minimum_total(mut triangle: Vec<Vec<i32>>) -> i32 {
for i in (0..triangle.len()-1).rev() { // from penultimate (last - 1) to first
let last_row = & triangle[i+1].clone();
let current_row = &mut triangle[i];
for j in 0..current_row.len() {
current_row[j] = cmp::min(last_row[j], last_row[j+1]) + current_row[j];
}
}
triangle[0][0]
}
fn main() {
println!("{}", minimum_total(vec![vec![2],vec![3,4],vec![6,5,7],vec![4,1,8,3]]));
}
As you can see, I used .clone() to fix the borrow checker errors that show up when you try to write a program using references:
use std::cmp;
fn minimum_total(mut triangle: Vec<Vec<i32>>) -> i32 {
for i in (0..triangle.len()-1).rev() { // from penultimate (last - 1) to first
let current_row = &mut triangle[i];
let last_row = &triangle[i+1];
for j in 0..current_row.len() {
current_row[j] = cmp::min(last_row[j], last_row[j+1]) + current_row[j];
}
}
triangle[0][0]
}
fn main() {
println!("{}", minimum_total(vec![vec![2],vec![3,4],vec![6,5,7],vec![4,1,8,3]]));
}
Terminal:
error[E0502]: cannot borrow `triangle` as immutable because it is also borrowed as mutable
--> src\main.rs:6:25
|
5 | let current_row = &mut triangle[i];
| -------- mutable borrow occurs here
6 | let last_row = &triangle[i+1];
| ^^^^^^^^ immutable borrow occurs here
7 | for j in 0..current_row.len() {
| ----------------- mutable borrow later used here
For more information about this error, try `rustc --explain E0502`.
However, when trying to write a program poorly everything works without any problems:
use std::cmp;
fn minimum_total(mut triangle: Vec<Vec<i32>>) -> i32 {
for i in (0..triangle.len()-1).rev() { // from penultimate (last - 1) to first
for j in 0..triangle[i].len() {
triangle[i][j] = cmp::min(triangle[i+1][j], triangle[i+1][j+1]) + triangle[i][j];
}
}
triangle[0][0]
}
fn main() {
println!("{}", minimum_total(vec![vec![2],vec![3,4],vec![6,5,7],vec![4,1,8,3]]));
}
You can accomplish this via the split_at_mut() method, which comes from the primitive slice type (which Vec auto-derefs to). This method allows you to safely take a mutable slice and split it into two mutable slices at a given index, since it's guaranteed that the two slices won't overlap. (Note this is zero-copy, as slices are just fat pointers borrowing an existing contiguous sequence.)
The two slices then are independent for the purposes of borrow checking, so you can borrow mutably from both slices at the same time (or, in your case, mutably from one and immutably from the other).
use std::cmp;
fn minimum_total(mut triangle: Vec<Vec<i32>>) -> i32 {
for i in (0..triangle.len()-1).rev() { // from penultimate (last - 1) to first
let (left, right) = triangle.split_at_mut(i + 1);
let current_row = left.last_mut().unwrap();
let last_row = right.first().unwrap();
for j in 0..current_row.len() {
current_row[j] = cmp::min(last_row[j], last_row[j+1]) + current_row[j];
}
}
triangle[0][0]
}
fn main() {
println!("{}", minimum_total(vec![vec![2],vec![3,4],vec![6,5,7],vec![4,1,8,3]]));
}
Yes, that's the thing with Rust -- you have to code in a way that the compiler can tell it is safe. Sometimes that requires a bit of thought, but often in the end you have code that is cleaner than you would have written otherwise.
Imagine having a function that could walk through items two at a time, calling a function you specify on them, with the first being immutable, and the second being mutable. Call it pairs_mut, and calling it with function f on a,b,c,d it would result in calls to f(&a, &mut b), f(&b, &mut c), and f(&c, &mut d). A non-generic version is not that hard to write. I am hesitant to put the code here because you are trying to learn from the exercise.
NOTE: I suspect that such a facility (or perhaps something more general) exists somewhere in the Rust ecosystem, but I have looked in Iterator and the itertools crate and didn't find anything. If you know of an existing facility like this, please share a link in a comment. Otherwise perhaps I should try to get something added to itertools.
Now given pairs_mut, I hope you can see that minimum_total could run it on triangle.rev() and do that bit of dynamic programming to come up with the minimum sum. Let me know if you want me to put some actual code here, but I encourage you to try it yourself first.
This question already has an answer here:
In Rust, what's the difference between "shadowing" and "mutability"?
(1 answer)
Closed 2 years ago.
I was quite surprised to find that the following program will happily compile and run (using "cargo 1.42.0 (86334295e 2020-01-31)."), outputting:
5
k
The variable x which is not declared as mut is not only reassigned but reassigned with a different type.
Is there some reason why you are allowed to do this?
fn main() {
let x = 5;
println!("{}", x);
let t: (i32, f64, char) = (2, 3.14, 'k');
let (_,_,x) = t;
println!("{}", x);
}
This is called "shadowing a variable"
(https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#shadowing)
It can also been shown as simply as so:
let x = 5;
let x = 'k';
It actually comes in handy often. For instance, you can reuse an identifier after you are done using its initially assigned value:
let two_times_five = 2 * 5; // type i32
let two_times_five = two_times_five.to_string(); // type String
The compiler will still enforce strong typing; accesses to two_times_five before its redefinition will be accessing an i32, accesses afterward will be accessing a String.
There are also times when you don't want a variable to be mutable, but at some point you want to assign it a different value. Using variable shadowing rather than let mut means you know the variable is not changed in between its definitions, regardless of what functions it's passed into or methods are called on it.
I'm wondering if someone can help me understand why this program behaves as it does:
fn main() {
let mut x = 456;
{
let mut y = Box::new(&x);
y = Box::new(&mut y);
println!("GOT {}",*y);
}
}
This program compiles under rust 1.35.0 (both 2015 and 2018 editions), and prints
GOT 456
But, I'm confused what's going on here. I'm guessing that this is an example of an auto-dereference. So, in reality, it looks like this:
fn main() {
let mut x = 456;
{
let mut y = Box::new(&x);
y = Box::new(&mut *y);
println!("GOT {}",*y);
}
}
Is that it?
This is a case of deref coercion, but one that is obfuscated by a few other unnecessary parts of the code. The following improvements should be made here:
The mut modifier on variable x is not needed because it is never modified.
The borrow of y in Box::new(&mut y) does not have to be mutable because the variable holds an immutable reference.
The println! implementation also knows to print values behind references, so the explicit * is not needed.
Then, we get the following code:
fn main() {
let x = 456;
{
let mut y = Box::new(&x);
y = Box::new(&y);
println!("GOT {}", y);
}
}
y is a variable of type Box<&i32> which is initially bound to a box created in the outer scope. The subsequent assignment to a new box works because the &y, of type &Box<&i32>, is coerced to &&i32, which can then be put in the box by automatically dereferencing the first borrow. This coercion is required because the variable x can only be assigned values of the same Box<&i32> type.
The lifetime of the reference inside both boxes also ended up being the same, because they refer to the same value in x.
See also:
What is the relation between auto-dereferencing and deref coercion?
I'm new to Rust and I don't understand the following piece of code:
let mut x = 5;
{
let y = &mut x;
*y += 1;
}
println!("{}", x);
Explanation from the Rust site:
You'll also notice we added an asterisk (*) in front of y, making it *y, this is because y is a &mut reference. You'll need to use astrisks [sic] to access the contents of a reference as well.
If *y is a reference, why does the following code work
fn main() {
let mut x = 5;
{
let y = &mut x;
println!("{}", y);
}
}
I know I'm not modifying the value here, but what is the difference and why
would y += 1; not work?
If *y is a reference
*y is not a reference. y is a reference; *y dereferences y, allowing you access to the referred-to value.
what is the difference [between += and println!]
println! is a macro that automatically references the arguments given to it. In addition, the Display trait (used via {} in the format string) is implemented for all references to types that themselves implement Display (impl<'a, T> Display for &'a T where T: Display + ?Sized).
Thus, println!("{}", y); is actually printing out a reference to a reference to a value. Those intermediate references are automatically dereferenced due to the implementation of Display.
+=, on the other hand, is implemented via the AddAssign trait. The standard library only implements adding an integer type to itself (impl AddAssign<i32> for i32). That means that you have to add an appropriate level of dereferencing in order to get both sides to an integer.