Functor and functor factories


#1

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?


#2

The macro would be resolved at compile time and would therefore just do what you had done if you had written it out by yourself, which seems to be exactly what you want.

PS: Passing closures around can be a problem if it is called later but uses variables which don’t live long enough.