-
fnis a function pointer. It is just a plain memory address where a function starts which requires that there are values provided (The arguments), it follows a certain abi (The"abi"inextern "abi" fns) and what values are returned. -
Fn,FnOnce,FnMutare all the traits which describe calling a function. These are generally referred to as theFn*family. These traits will permit you to use call syntax. Iffis a value whose type implementsFn(We'll use this for the example since this makes it the easiest to explain), then we can callfusing the standard function call syntax:f(x)orf(), etc. (Note however, that iffis a field on a type, then we must say(my_val.f)()). This is considered an operator, and is therefore understd::ops. -
Box<dyn Fn()>is a boxed up value which implementsFn. That means, that it could be a closure,fnpointer, or a custom type. Note thatfn-style pointers will automatically implement all of theFn*. This is actually one of the most impeding forms of function values, since you must box it up, and call it through dynamic dispatch (Which has its own downsides for speed). - A generic parameter, be it
fn foo<F: Fn()>(my_func: F), or usingimplsyntax:fn foo(my_func: impl Fn())would be the best choice (But not the most flexible for you, the one who's implementing the functionfoo). It allows either of the two I discussed above, or, a special third one: - Specific function pointers. They're special. They have an unnameable type and are actually the function that they point to. They're not the address, they're the function name. They can implicitly coerce into
fnpointers, to not break code like the following:
But, they allow optimizations to occur like as if the receiver were actually calling the function, and not just an opaque pointer.fn foo() {} let x: fn() = foo;
Thanks for reading my spiel about function pointers, have a nice day.
Read @RustyYato's Closures: Magic Function post for more info on how closures work.
PS. You can write code using the following syntax on the forum:
```
code
```