Is there any way to construct a callable value in the stable version of Rust?

Consider a certain API that is designed as follows:

pub fn update<F>(f:F) where F:FnOnce(i32){/* ... */}

Besides using closure to capture the environment variable, is there any way to construct a customized data structure that is callable in the stable version of Rust? Something like this:

struct Callable{
   data: Data,
}
update(Callable{data:Data{/* ... */}});

no.

the "unsugared" FnOnce trait is not stable, and I don't think it will be stablized soon (or ever).

in some cases, you can use a custom trait and a blanket implementation as a workaround, but you don't really call the value like a closure, you'll have to use a regular trait methods:

trait MyFnOnceI32 {
    type Output;
    fn call_once(self, arg: i32) -> Self::Output;
}
impl<F, R> MyFnOnceI32 for F where F: FnOnce(i32) -> R {
    type Output = R;
    fn call_once(self, arg: i32) -> R {
        self(arg)
    }
}

pub fn update<F>(f: F) where F: MyFnOnceI32<Output = ()> {
    f.call_once(42);
}

struct Callable {
    data: Data
}

impl MyFnOnceI32 for Callable {
    type Output = ();
    fn call_once(self, arg: i32) {
        todo!()
    }
}

update(|x: i32| do_something());
update(Callable{ data: Data {}}); 

see also the fn-traits crate.

1 Like

However, this approach is based on I can control the signature of update, but it's not possible because update is in the upstream crate.

yeah, that's what I meant by "in some cases".

anyways, I don't know the reason you didn't want to use a closure in the first place, but you can also make an adapter for the custom callback trait by simply wrapping it in a closure:

fn into_closure<F>(f: F) -> impl FnOnce(i32)
where F: MyFnOnceI32<Output = ()>
{
    move |arg| f.call_once(arg)
}

update(into_closure(Callable { data: Data {} }));

or, equivalently, create a wrapper for update():

fn my_update<F: MyFnOnceI32<Output=()>>(f: F) {
    update(|arg| f.call_once(arg))
}