| ▲ | andy_xor_andrew 4 hours ago | |||||||
if I'm not mistaken (and I very well may be!) my primary confusion with closures comes from the fact that: the trait they implement (FnOnce / Fn / FnMut) depends entirely upon what happens inside the closure. It will automatically implement the most general, relaxed version (FnMut I think?) and only restrict itself further to FnOnce and Fn based on what you do inside the closure. So, it can be tricky to know what's going on, and making a code change can change the contract of the closure and therefore where and how it can be used. (I invite rust experts to correct me if any of the above is mistaken - I always forget the order of precedence for FnOnce/Fn/FnMut and which implies which) | ||||||||
| ▲ | yoshuaw 2 hours ago | parent | next [-] | |||||||
> I always forget the order of precedence for FnOnce/Fn/FnMut The way I remember the ordering is by thinking about the restrictions the various Fn traits provide from a caller's perspective:
So going from most to least restrictive gives you `FnMut: FnOnce` and `Fn: FnMut`. | ||||||||
| ||||||||
| ▲ | krukah an hour ago | parent | prev | next [-] | |||||||
Easiest mnemonic to remember precedence is simply ordering by the length of their names. FnOnce FnMut Fn | ||||||||
| ▲ | KolmogorovComp 3 hours ago | parent | prev | next [-] | |||||||
This is correct. But it’s not really surprising, it’s type inference. | ||||||||
| ||||||||
| ▲ | umanwizard 2 hours ago | parent | prev [-] | |||||||
The least restrictive for the caller is Fn (you can call it whenever), then FnMut (you can call it only if you have exclusive access to it, as many times as you want), then FnOnce (you can call it only if you have exclusive owned access, and calling it once destroys it). The least restrictive for the function itself is the opposite order: FnOnce (it can do anything to its environment, including possibly consuming things without putting them back into a consistent state), followed by FnMut (it has exclusive access to its environment, and so is allowed to mutate it, but not destroy it), followed by Fn (it has only shared access to its environment and therefore is not allowed to mutate it). Since these orders are inverses of each other, functions that are easier to write are harder to call and vice versa. That’s why they implement the trait with the minimum amount of power possible, so that they can be called in more places. | ||||||||