I have following code in rust and this one i working. Here i define fuinction that mutates the argument passed by reference.
fn inc (v: &mut i32){
*v+=1;
}
fn main() {
let mut n = 0;
// let mut inc = || n += 1;
inc(&mut n); // call the closure to increment n
println!("n = {}", n); // prints "n = 1"
inc(&mut n); // call the closure again to increment n
println!("n = {}", n); // prints "n = 2"
inc(&mut n); // call the closure again to increment n
println!("n = {}", n); // prints "n = 3"
}
I tried using a named function instead of an anonymous one (the first example in my question)
in the code example above I have function inc than at takes argument by reference and increments it. Is it somehow possible to define anonymous lambda instead that will do the same task? Ideally it would to have something similiar to the following code to be working:
fn main() {
let mut n = 0; let mut inc = || n += 1;
inc(); // call the closure to increment n
println!("n = {}", n); // prints "n = 1"
inc(); // call the closure again to increment n
println!("n = {}", n); // prints "n = 2"
inc(); // call the closure again to increment n
println!("n = {}", n); // prints "n = 3"
}
The problem is that the lambda (continuously) borrows n for basically its entire lifetime, and while there is a mutable borrow to a value, no other borrows can co-exist. So this pattern is not really expressible in safe Rust (exactly because it's error-prone).
You can either use some form of interior mutability (e.g., Cell, RefCell, Mutex, etc.), but for such a simple case, it's not really idiomatic. If you can realize this by passing a borrow of the value to a function, you should just do that. (It's more readable anyway, due to the reader knowing exactly what state the function will modify.)
Thanks for answering. I hope I can ask several questions about borrowing and Rust ideology here. Do I correctly understand that once i pas non-primitive data ass argument to function it is moved and I cannot read it anymore?
like this
let var = SomeStruct{};
modify_data(var); // mutable referedce
modify_data(var); // second mutable reference
Do I also correctly understand that the only solution to pass mutable reference is to return the reference back from function like this.
let modified_value=func_call(val):
let modified_value_2=func_call(modified_value):
or even like this:
val=func_call(val):
val=func_call(val):
Why are other options considered unsafe?
Also can I achive this effect using data stored on heap to achieve this task, for example store several references to one boxed value?
Passing a value to a function moves it, just like assigning it to a variable does. This is true of all types, not just non-primitives.
You might be confusing "primitive" with "Copy". Values of a type that implements Copy will not be invalidated when moved from, they will be copied instead.
I don't understand how this snippet is relevant; you are passing var by-value to the function, there are no mutable references at all.
No, a mutable reference is passed by taking the address, like this:
func_call(&mut val);
But for basic stuff like this, please read The Book.
I'm not sure what specific "other options" you are referring to. If you don't know why sharing-xor-mutability must be upheld, read this.
You can create references to values on the stack or on the heap, or anywhere else, really. Whether a value is on the stack or the heap does not affect borrowing rules. References don't have different types based on whether they point to the stack or the heap or any other memory region. The borrowing rules are the same: you can borrow a value immutably as many times as you like, or borrow it immutably exactly once at a time.
you cannot do this using compiler generated closures, but you can define your own "closure"-like type in nightly rust using unstable features. just note, you exclusively borrows the variable, so you can't access the original variable directly, but you can define a "accessor" on the borrowing type.
fn main() {
let mut x = 42;
let mut inc = Inc::new(&mut x);
inc();
dbg!(inc.get());
inc();
dbg!(inc.get());
}
i kind of came up with a similiar idea like this. It is not state but ;Adder; but the idea is the same, it requires to be called to react data and if you call it with arg 0 you get data itself, it can be modified to be called without an argument i know