TL; DR: В качестве аргумента следует использовать F: Fn() -> ()
или impl Fn() -> ()
.
Fn
Как @Bubletan упомянул в своем ответе , ключевой момент заключается в том, что Fn
это автоматически реализовано для &F
, если F
реализует Fn
:
impl<'_, A, F> Fn<A> for &'_ F
where
F: Fn<A> + ?Sized,
Следствием является то, что:
foo(f: impl Fn() -> ())
можно назвать и с foo(callable)
или foo(&callable)
.
foo(f: &impl Fn() -> ())
заставляет вызывающего абонента использовать foo(&callable)
и запрещать foo(callable)
.
В общем, лучше оставить выбор вызывающему, когда для вызываемого абонента есть недостатки, и поэтому предпочтительнее использовать первую форму.
FnMut
Та же логика применяется к FnMut
, который также автоматически реализуется для &mut F
, если F
реализует FnMut
:
impl<'_, A, F> FnMut<A> for &'_ mut F
where
F: FnMut<A> + ?Sized,
Что, следовательно, должно также передаваться по значению в аргументах, оставляя вызывающей стороне выбор относительно того, предпочитают ли они foo(callable)
или foo(&mut callable)
.
FnOnce
Существует аргумент согласованности с FnOnce
, который может быть передан только по значению, что опять-таки указывает в направлении получения аргументов семейства Fn*
по значению.