I want to enter a loop with a variable n
which is borrowed by the function. At each step, n
takes a new value; when exiting the loop, the job is done, with the help of other variables, and n
will never be used again.
If I don't use references, I have something like this:
fn test(n: Thing) -> usize {
// stuff
let mut n = n;
for i in 1..10 {
let (q, m) = n.do_something(...);
n = m;
// stuff with x
}
x
}
x
is the result of some computation with q
and m
but it is an usize
type and I didn't encounter any issue in this part of the code. I didn't test this code, but this is the idea. I could make code written like this work.
Since I want to do it with a reference; I tried to write:
fn test(n: &Thing) -> usize {
// stuff
let mut n = n;
for i in 1..10 {
let (q, m) = (*n).do_something(...);
n = &m;
// stuff with x
}
x
}
Now the code will not compile because m
has a shorter lifetime than n
. I tried to make it work by doing some tricky things or by cloning things, but this can't be the right way. In C, the code would work because we don't care about what n
is pointing to when exiting the loop since n
isn't used after the loop. I perfectly understand that this is where Rust and C differ, but I am pretty sure a clean way of doing it in Rust exists.
Consider my question as very general; I am not asking for some ad-hoc solution for a specific problem.
The best way to make the condition change from True to False is to use a variable as part of the Boolean expression. We can then change the variable inside the while loop.
Using While loop: We can't directly increase/decrease the iteration value inside the body of the for loop, we can use while loop for this purpose.
A for-loop uses an iterator over the range, so you can have the ability to change the loop variable. Consider using a while-loop instead. That way, you can update the line index directly.
You can modify the loop variable in a for loop, the problem is that for loops in Python are not like "old-style" for loops in e.g. Java, but more like "new-style" for-each loops. In Python, for i in range(0, 10): does not behave like for (int i = 0; i < 10; i++) { , but like for (int i : new int[] {0, 1, ..., 10}} .
As Chris Emerson points out, what you are doing is unsafe and it is probably not appropriate to write code like that in C either. The variable you are taking a reference to goes out of scope at the end of each loop iteration, and thus you would have a dangling pointer at the beginning of the next iteration. This would lead to all of the memory errors that Rust attempts to prevent; Rust has prevented you from doing something bad that you thought was safe.
If you want something that can be either borrowed or owned; that's a Cow
:
use std::borrow::Cow;
#[derive(Clone)]
struct Thing;
impl Thing {
fn do_something(&self) -> (usize, Thing) {
(1, Thing)
}
}
fn test(n: &Thing) -> usize {
let mut n = Cow::Borrowed(n);
let mut x = 0;
for _ in 1..10 {
let (q, m) = n.do_something();
n = Cow::Owned(m);
x = x + q;
}
x
}
fn main() {
println!("{}", test(&Thing));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With