Reputation: 6646
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?
Upvotes: 2
Views: 174
Reputation: 3875
Perhaps you can use a reference, if you’re using types that support addition on references (probably all the useful ones do, including the built-in numeric types).
fn make_adder<T, U>(x: T) -> impl Fn(T) -> U
where
for<'a> &'a T: Add<T, Output = U>,
{
move |y| &x + y
}
or
fn make_adder<'a, T>(x: &'a T) -> impl Fn(T) -> <&'a T as Add<T>>::Output
where
&'a T: Add<T>,
{
move |y| x + y
}
Upvotes: 2
Reputation: 432089
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
}
Upvotes: 3