I have a generic algorithm function that takes a function argument. Say:
fn foo(f: F) -> Res where F: Fn(Arg) -> Res
now I often need to call it with a closure like this:
|a| { bar(p, a) }
where bar
is
fn bar(p: Param, a: Arg) -> Res
I don't want to write literal foo(|a| { bar(p, a) })
all over the place, because it is just noise. Instead I'd prefer something like foo(make_bar(p))
.
Now in C++ I'd simply write a functor like
struct Bar {
Param p;
Res operator()(Arg a) { return bar(p, a); }
};
Bar make_bar(Param p) { Bar res = { p }; return res; }
(of course I wouldn't write a separate bar
function, but inline it in the Bar
functor).
This way the function to call (Bar::operator()
) would still be part of type information, so the compiler can inline it in the monomorphisation.
But in Rust the std::ops::Fn
trait is unstable, so I can't implement it (at least not in anything that is supposed to be published and used with stable rustc
). So what options do I have?
- Return a boxed closure (
fn make_bar(p: Param) -> Box<Fn(Arg) -> Res>
). Except that now requires allocation and basically kills the optimization. - Use custom trait and possibly provide a blanket implementation for
T: Fn(Arg) -> Res
and create a struct implementing it. That shouldn't kill optimizations, but it's a bit verbose. - Use
make_bar!
macro instead of function, but it feels somewhat convoluted.
What would be the most idiomatic approach?