Understanding Iter with FnMut - rust

Since Iter's "all" fn takes type FnMut is it possible to update the element while checking for condition and short circuiting? Though I understand it is not supposed to, but what prevents it from updating the value?
fn main() {
let a = ["as", "zz"];
let mut iter = a.iter();
iter.all(|& (mut x)| {x = "cc"; true});
for z in a.iter(){
println!("{z}");
}
}
Above prints
as
zz
In above case why setting "x = cc" not work?
Or Alternatively why does Iter "all" method takes F of type FnMut and not Fn when it is not supposed to mutate but only validate for condition

x = "cc" does not change the value referred by x, instead it changes the reference itself (i.e. it makes it refer to another value), as evidenced by this example:
fn main() {
let a = ["as", "zz"];
let mut iter = a.iter();
iter.all(|&(mut x)| {
println!("before: {:?}", x as *const _);
x = "cc";
println!("after: {:?}", x as *const _);
true});
for z in a.iter(){
println!("{z}");
}
}
Playground
Note that this has nothing to do with the fact that the closure is FnMut, which only means that it may change any captured values as in:
fn main() {
let a = ["as", "zz"];
let mut count = 0;
let mut iter = a.iter();
iter.all(|&_x| {
count += 1; // This is possible because the closure is `FnMut`
true});
println!("Count: {count}");
for z in a.iter(){
println!("{z}");
}
}
Playground

Do not be mistaken! A function implementing FnMut means that it captures a receiving context mutably. It does not mean that its items may be modified from its original source.
let mut k = 0;
assert_eq!((10..15)..all(|x| {
k += 1;
x > k
}), true);
Given
let mut iter = a.iter();
we have an iterator the items of which are references to elements in vector a. And these references are immutable. In order to have an iterator which allows you to mutate the items in a vector, use iter_mut.
let iter = a.mut_iter();
iter.all(|x| { *x = "cc"; true});
for z in a.iter(){
println!("{z}");
}
This would still not require FnMut in particular, since it does not capture any context other than the items iterated on. The adaptor all (and many other iterator adaptors) were designed to constrain to FnMut so that the closures passed as their first parameter are allowed to keep and manipulate some external state for whichever logic they intend to do. Since the closure is called sequentially in the same thread, this is always memory safe.
See also:
What's the difference between placing "mut" before a variable name and after the ":"?
When does a closure implement Fn, FnMut and FnOnce?

Related

Rust peekable double reference

Why does a peekable iterator return a double reference in an Option?
struct Foo {}
let mut foovec = vec![];
foovec.push(Foo {});
let mut iter = foovec.iter().peekable();
let next = iter.peek();
next is an Option<&&Foo>, not an Option<&Foo>.
How do I get it to be the latter?
I do not want to use .into_iter() because I do not want to consume the vec. I just want a borrowed reference to the Foo struct wrapped in an Option.
peek yields references to whatever you're iterating over. If that's also references, it'll yield double references. You can use the copied Option adapter to remove that level of indirection:
struct Foo {}
let mut foovec = vec![];
foovec.push(Foo {});
let mut iter = foovec.iter().peekable();
// use `copied` here to go from Option<&&_> to Option<&_>
let next = iter.peek().copied();
Alternatively, you can just call next after you checked that you want the peeked value:
struct Foo {}
let mut foovec = vec![];
foovec.push(Foo {});
let mut iter = foovec.iter().peekable();
if is_okay(iter.peek()) {
let next = iter.next(); // `next` has type `&Foo`
}
You could even use pattern matching to remove one level of indirection:
if let Some(&next) = iter.peek() {
// `next` has type `&Foo` in this block
}

A variable modified by two closures

Consider the following (contrived) way to increment x by 9.
fn main() {
let mut x = 0;
let mut f = || {
x += 4;
};
let _g = || {
f();
x += 5;
};
}
error[E0499]: cannot borrow `x` as mutable more than once at a time
--> x.rs:6:12
|
3 | let mut f = || {
| -- first mutable borrow occurs here
4 | x += 4;
| - first borrow occurs due to use of `x` in closure
5 | };
6 | let _g = || {
| ^^ second mutable borrow occurs here
7 | f();
| - first borrow later captured here by closure
8 | x += 5;
| - second borrow occurs due to use of `x` in closure
error: aborting due to previous error
For more information about this error, try `rustc --explain E0499`.
So, it does not work. How to make an algorithm like the above that would modify a variable in a closure and call another closure from it that also modifies the variable?
In traditional languages it's easy. What to do in Rust?
The accepted answer is the most idiomatic approach, but there is also an alternative that is useful in situations when the additional argument doesn't work, for example when you need to pass the closure to third-party code that will call it without arguments. In that case you can use a Cell, a form of interior mutability:
use std::cell::Cell;
fn main() {
let x = Cell::new(0);
let f = || {
x.set(x.get() + 4);
};
let g = || {
f();
x.set(x.get() + 5);
};
f();
g();
assert_eq!(x.get(), 13);
}
By design, closures have to enclose external objects that are used in it upon creation, in our case closures have to borrow the external x object. So as compiler explained to you, upon creation of the closure f it mutably borrows x, and you can't borrow it once again when you create closure g.
In order to compile it you can't enclose any external object that you want to change. Instead you can directly pass the objects as a closure's argument (arguably it's even more readable). This way you describe that a closure accepts some object of some type, but you don't yet use/pass any actual object. This object will be borrowed only when you call the closure.
fn main() {
let mut x = 0;
let f = |local_x: &mut i32| { // we don't enclose `x`, so no borrow yet
*local_x += 4;
};
let _g = |local_x: &mut i32| { // we don't enclose `x`, so no borrow yet
f(local_x);
*local_x += 5;
};
_g(&mut x); // finally we borrow `x`, and this borrow will later move to `f`,
// so no simultaneous borrowing.
println!("{}", x); // 9
}
To expand on Alex Larionov's answer: you should think of a closure as a callable structure, anything you capture is set as a field of the structure, then implicitly dereferenced inside the function body. The way those fields are used is also what determines whether the closure is Fn, FnMut or FnOnce, basically whether the method would take &self, &mut self or self if it were written longhand.
Here
fn main() {
let mut x = 0;
let mut f = || {
x += 4;
};
// ...
}
essentially translates to:
struct F<'a> { x: &'a mut u32 }
impl F<'_> {
fn call(&mut self) {
*self.x += 4
}
}
fn main() {
let mut x = 0;
let mut f = F { x: &mut x };
// ...
}
from this, you can see that as soon as f is created, x is mutably borrowed, with all that implies.
And with this partial desugaring, we can see essentially the same error: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=e129f19f25dc61de8a6f42cdca1f67b5
If we use the relevant unstable features on nightly we can get just a bit closer. That is pretty much what rustc does for us under the hood.

Mutability in fields for structs in Rust

I'm still new with Rust but I have doubts about how mutability works for fields in structs. Specifically how we can modify fields that originally were immutable. For example:
struct Point {
x: isize,
y: isize,
}
impl Point {
fn new(x: isize, y: isize) -> Self {
Self { x, y }
}
fn set_x(&mut self, new_x: isize) {
self.x = new_x;
}
}
struct Line {
p: Point,
q: Point,
}
impl Line {
fn new(p: Point, q: Point) -> Self {
Self { p, q }
}
fn set_x_in_p(&mut self, new_x: isize) {
self.p.set_x(new_x);
}
}
fn main() {
// Both x and y are immutable
let p = Point::new(0, 0);
let q = Point::new(1, 1);
// Line IS mutable
let mut line = Line::new(p, q);
// Modifying point p (originally immutable) with a new x
line.set_x_in_p(999);
}
Instead with references we cannot
let x = 3;
let y = &mut x; // does not work because x originally is immutable
So, how does it work? Thanks.
In your example, p and q are indeed immutable, but then you move them into a Line instance with the constructor, since they're passed by value and don't implement Copy to enable implicit copying. This means that the original bindings (p and q) are no longer valid (the compiler will prevent you from using them) and the values are instead accessible only via the mutable line binding, which allows mutating its members. Essentially, it's not the values that are mutable, but rather their bindings. For example, the following code can be used to re-bind a value to change its mutability:
let x = String::from("hello world"); // using String as an example of a non-Copy type
let mut x = x; // this shadows the previous binding with a mutable one of the same name
x.make_ascii_uppercase(); // we can now mutate the string
let x = x; // shadow the mutable binding with an immutable one
println!("Result: {}", x);
This example works because we have direct control over the value, and can move/bind it as desired. Introducing references would limit what could be done - for example, the following examples wouldn't work:
let x = String::from("hello world");
let x_ref = &x; // create an immutable reference to x
let mut x_mut = x; // error - we can't move x while it's borrowed
let x_mut_ref = &mut x; // error - we can't create a mutable reference while any other references exist
I'd recommend reading the ownership and moves page of Rust by example, which explains it pretty well.
When you are declaring x, you are specifying it as immutable with the let instead of let mut. When you then declare y and initialize it as &mut x you are attempting to borrow x. In Rust, the one thing you can never do is simultaneously have shared ownership AND mutability.
Check out what Niko Matsakis has to say about ownership.

Mutate vector within filter

So, I have the following code successfully performing filter in vector:
let mut v1 : Vec<i32> = vec!(1,2,3);
let v2 : Vec<&mut i32> = v1.iter_mut().filter(|x| {**x == 2}).collect();
println!("{:?}", v2);
Since the type signature of the predicate in the filter function is
FnMut(&Self::Item) -> bool, I was assuming that that mutation inside
the closure will work:
let mut v1 : Vec<i32> = vec!(1,2,3);
let v2 : Vec<&mut i32> = v1.iter_mut().filter(|x| {**x = 3; **x == 2}).collect();
println!("{:?}", v2);
But the above code results in a compile error. How to fix that ? Note
that I'm playing with rust to get a better understanding, so the abpve
example doesn't make sense (usually, nobody will try to mutate
things inside filter).
You are confusing two concepts: FnMut means that a function can change its captured variables, like:
fn main() {
let v1 = vec![1, 2, 3];
let mut i = 0usize;
let v2: Vec<_> = v1
.into_iter()
.filter(|x| {
i = i + 1;
*x == 2
})
.collect();
println!("We iterate {} times and produce {:?}", i, v2);
}
This doesn't mean that every parameter of a function will be mutable.
In your code, filter() takes a &Self::Item, which is very different from the map() one that takes Self::Item. Because the real type will translate to Map<Item=&mut i32> and Filter<Item=&&mut i32>. Rust forbids you from mutating a reference if it's behind a non mutable reference:
fn test(a: &&mut i32) {
**a = 5;
}
error[E0594]: cannot assign to `**a` which is behind a `&` reference
This is because Rust follows the the-rules-of-references:
At any given time, you can have either one mutable reference or any number of immutable references.
References must always be valid.
This means you can have more than one &&mut but only one &mut &mut. If Rust didn't stop you, you could mutate a &&mut and that would poison any other &&mut.
Unfortunately the full error description of E0594 is still not available, see #61137.
Note: Avoid side effects when you use the iterator API, I think it's OK to mutate your FnMut state but not the item, you should do this in a for loop, like:
fn main() {
let mut v1 = vec![1, 2, 3];
for x in v1.iter_mut().filter(|x| **x == 2) {
*x = 1;
}
println!("{:?}", v1);
}

Why do Arc and Mutex allow me to change the value of an immutable variable?

Take this example:
fn main() {
let dato = std::sync::Arc::new(std::sync::Mutex::new(1u8));
for _ in 0..3 {
let value = dato.clone();
std::thread::spawn(move || {
let v = value.lock().unwrap();
*v += 1; // <- Error
});
}
std::thread::sleep(std::time::Duration::from_secs(1u64));
println!("{:?}", dato);
}
cannot borrow immutable local variable v as mutable
I know that changing to mut works:
std::thread::spawn(move || {
let mut v = value.lock().unwrap();
*v += 1;
});
but why does this work:
let value = dato.clone();
std::thread::spawn(move || {
*value.lock().unwrap() += 1;
});
playground
value.lock().unwrap() returns a value of type MutexGuard, which has a DerefMut implementation:
impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> {
fn deref_mut(&mut self) -> &mut T { ... }
}
DerefMut::deref_mut(x) is equivalent to &mut *x; naturally, DerefMut is also used for assignments under the pointer, like in your case.
Therefore, for *v += 1 to work, v should be a mut variable - otherwise it would be impossible for DerefMut::deref_mut to be invoked at all.
*value.lock().unwrap() += 1 works because now value.lock().unwrap() is a temporary variable without an explicit binding, so Rust is free to assign its mutability automatically.
The fact that Mutex contains an UnsafeCell inside is not related to this particular thing about DerefMut directly; however, it does mean that Mutex provides something called internal mutability, i.e. it allows one to mutate its contents through a shared reference. You can read more on it in the book.

Resources