Search code examples
rustfunctional-programmingclosures

Should I use Fn, FnMut and FnOnce only for closures?


Scenario: I want to write an optimiser algorithm which takes a univariate function as an argument. I want it to work both with closures and structs implementing some method to calculate the value of the optimised function. Should I declare my optimiser as taking an FnMut argument or some other trait which would be implemented by any struct I want to pass to the optimiser?


Solution

  • You can't (yet) implement the Fn traits yourself on stable Rust. You should probably define your own trait that does the computation which you can then implement for your structs and for any type that implements Fn (or FnMut):

    // I'm opting for `&mut self` here as it's more general
    // but this might not be necessary for your use case
    trait Calculate<T, U> {
        fn calculate(&mut self, t: T) -> U;
    }
    
    // Because `Fn: FnMut` this will also implement `Calculate` for `Fn`.
    impl<F, T, U> Calculate<T, U> for F
    where F: FnMut(T) -> U {
        fn calculate(&mut self, t: T) -> U {
            (self)(t)
        }
    }
    
    struct State {
        flag: bool,
    }
    impl<T, U> Calculate<T, U> for State
    where T: Into<U> {
        fn calculate(&mut self, t: T) -> U {
            self.flag = true;
            // or whatever calculation you actually need to do here
            t.into()
        }
    }