Good day!
Warning: just starting to learn Rust, a beginner, although like it a lot so far.
I faced a problem with generic parametrisation and not sure if it's possible to express it Rust. Below comes very simplified example showing the problem.
#[test]
fn it_works() {
assert_eq!(239, generic_apply(f, I32(239)));
}
pub trait ToI32 {
fn to_i32(&self) -> i32;
}
pub struct I32(i32);
pub struct I32B(i32);
impl ToI32 for I32 {
fn to_i32(&self) -> i32 {
self.0
}
}
impl ToI32 for I32B {
fn to_i32(&self) -> i32 {
self.0
}
}
pub fn convert<Arg: ToI32>(a: Arg) -> I32B {
I32B(a.to_i32())
}
#[cfg(feature = "dynamic")]
pub fn generic_apply<F, Arg>(f: F, a: Arg) -> i32
where Arg: ToI32,
F: Fn(&ToI32) -> i32
{
f(&convert(a) as &ToI32)
}
#[cfg(feature = "dynamic")]
pub fn f(a: &ToI32) -> i32 {
a.to_i32()
}
#[cfg(feature = "generic")]
pub fn generic_apply<F, Arg>(f: F, a: Arg) -> i32
where Arg: ToI32,
F: Fn(/* What to put here??? */) -> i32,
{
f(convert(a))
}
#[cfg(feature = "generic")]
pub fn f<Arg: ToI32>(a: Arg) -> i32 {
a.to_i32()
}
dynamic case is fine, but imagine that I want to optimise dynamic invocation via trait object. To achieve that I try to pass generic function (see case of generic) which can operate on any I32 object. And here comes my problem: I don't want to fix the actual type of the only argument passed to f---it may change due to implementation change, for example, if I remove convert in generic_apply body (in my real case I want to pass something which implements Iterator into f, but as I can change my chain of iterators, I don't want to change the signature due to it.) So, I want roughly Fn(* : I32) meaning some unspecified type as f is generic anyway.
My immediate feeling it is not possible in Rust and may, for example, render separate compilation impossible. But maybe I miss something obvious.
Thank you very much in advance!
cheers,
anton.