Taking example snippets from here: the following doesn't compile
fn foobar<F>(mut f: F)
where F: FnMut(i32) -> i32
{
println!("{}", f(f(2)));
// error: cannot borrow `f` as mutable more than once at a time
}
fn main() {
foobar(|x| x * 2);
}
but this does
fn foobar<F>(mut f: F)
where F: FnMut(i32) -> i32
{
let tmp = f(2);
println!("{}", f(tmp));
}
fn main() {
foobar(|x| x * 2);
}
I don't understand why the first snippet is illegal: it's effectively the same as the second one, just written more concisely. More specifically, why must f(f(2))
mutably borrow f
twice? It can simply borrow the inner f
to compute the value of f(2)
, and then borrow the outer f
and apply it to the value.
Use FnMut as a bound when you want to accept a parameter of function-like type and need to call it repeatedly, while allowing it to mutate state. If you don’t want the parameter to mutate state, use Fn as a bound; if you don’t need to call it repeatedly, use FnOnce.
Since FnOnce is a supertrait of FnMut, any instance of FnMut can be used where a FnOnce is expected, and since Fn is a subtrait of FnMut, any instance of Fn can be used where FnMut is expected. Use FnMut as a bound when you want to accept a parameter of function-like type and need to call it repeatedly, while allowing it to mutate state.
If you call a line that is call-out only, then you won’t get an answer. Usually, a system is in place to prevent ringing, and you might even get an automated message with the correct number to call. Sometimes, that isn’t set up correctly (or at all), and the line will ring until it drops.
Plenty of call centers will rig the phones to dial out but never answer an incoming call. If you call a line that is call-out only, then you won’t get an answer. Usually, a system is in place to prevent ringing, and you might even get an automated message with the correct number to call.
More specifically, why must
f(f(2))
mutably borrow f twice?
The borrows here happen in the order of expression evaluation, and expression evaluation is always left-to-right, even when the expressions in question are trivial variable accesses. The expressions to be evaluated in this code are:
f(f(2))
is made up of two subexpressions: f
and f(2)
.
f
(and borrow it as &mut
because we're calling a FnMut
).f(2)
.
f
; error because it's already borrowed.
2
.f
with the argument, 2
. This is the result of f(2)
.f
with the argument, the result of evaluating f(2)
. This is the result of f(f(2))
The borrow checker could soundly accept this case, but it would require the idea of recognizing that the first borrow hasn't been used yet, which isn't currently a thing in the borrow checker.
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