user3698446
user3698446

Reputation: 107

what does it mean for FnMut to take an immutable reference?

pub fn sort_by_key<K, F>(&mut self, mut f: F)
where
    F: FnMut(&T) -> K,
    K: Ord,
{
    merge_sort(self, |a, b| f(a).lt(&f(b)));
}

Here FnMut takes an immutable reference &T, what does it mean?

Isn't FnMut supposed to take a mutable reference &mut T?

Upvotes: 0

Views: 167

Answers (1)

mousetail
mousetail

Reputation: 8010

No, a FnMut means this function may use a mutable reference to a caputred variable. For example, take this function:

let mut x = 5;
{
    let mut square_x = || x *= x;
    square_x();
}
assert_eq!(x, 25);

This function takes no arguments. Certainly no immutable arguments. Yet it's considered a FnMut because it captures the mutable reference to x and mutates. it.

Note that Fn is a subtype of FnMut. Thus, any function that takes a FnMut can also be passed a function that does not mutate state. In this case, |a, b| f(a).lt(&f(b)) is just a Fn. It can be called multiple times and mutates no state. But any Fn is also a valid FnMut and any FnMut or Fn is also a valid FnOnce.

This does mean Fn can take a mutable reference as a parameter, so this is valid:

let b:Box<dyn Fn(&mut u8)->()> = Box::new(|a|*a+=1);

This function uses a mutable reference yet it's a Fn not a FnMut since it doesn't capture any variables.

See also this question for a lot more details

Upvotes: 2

Related Questions