Search code examples
rustclosuresclone

How do I make a closure that avoids a redundant clone of captured variables?


I'm trying to implement the classic make_adder function which takes an addable thing and returns a closure which takes another addable thing and returns the sum. Here is my attempt:

use std::ops::Add;

fn make_adder<T: Add + Clone>(x: T) -> impl Fn(T) -> T::Output {
    move |y| x.clone() + y
}

Because I don't want to restrict T to be Copy, I'm calling clone() inside the closure. I think this also means there will always be one redundant x captured by the closure as the "prototype". Can I somehow do this better?


Solution

  • Realistically, you cannot avoid this. You never know if the closure will be called another time; you will need to keep the value in case it is. I wouldn't worry about performing the clone until profiling has identified that this is a bottleneck.


    In certain cases, you might be able to change your closure type to FnOnce, which enforces that it can only be called exactly once:

    fn make_adder<T>(x: T) -> impl FnOnce(T) -> T::Output
    where
        T: Add,
    {
        move |y| x + y
    }
    

    In other cases, you might be able to add some indirection to the problem. For example, instead of passing a T, pass in a closure that generates a T (presumably not by cloning its own captured variable...). This T can always be consumed directly:

    fn make_adder<T>(x: impl Fn() -> T) -> impl Fn(T) -> T::Output
    where
        T: Add,
    {
        move |y| x() + y
    }