我希望能够将通用函数传递给另一个函数(在本例中为闭包),而不会丢失传递函数的“通用性”。由于这是一个令人费解的语句,因此下面是一个示例:
use std::fmt::Debug;
fn test<F, I: Debug>(gen: F) where F: Fn(fn(I) -> I) -> I {
fn input<I: Debug>(x: I) -> I {
x
}
println!("{:?}", gen(input));
}
fn main() {
test(|input| {
input(10);
input(10.0)
});
}
这不会编译,因为的值input
是类型推断的,不再通用。
完整错误:
<anon>:14:15: 14:19 error: mismatched types:
expected `_`,
found `_`
(expected integral variable,
found floating-point variable) [E0308]
<anon>:14 input(10.0)
^~~~
这样的东西有可能生锈吗?
编辑:
基于给出的解决方案,我使用以下方法解决了类似的问题:
#![feature(unboxed_closures)]
#![feature(fn_traits)]
use std::ops::Fn;
use std::ops::Add;
use std::ops::FnMut;
use std::fmt::Debug;
struct Builder;
impl Builder {
pub fn build<A: Add<B>, B: Add<A>>(&self) -> fn(A, B) -> <A as std::ops::Add<B>>::Output {
fn c<A: Add<B>, B: Add<A>>(a: A, b: B) -> <A as std::ops::Add<B>>::Output {
a + b
}
return c;
}
}
impl<A: Add<B>, B: Add<A>> Fn<(A, B)> for Builder {
extern "rust-call" fn call(&self, args: (A, B)) -> <A as std::ops::Add<B>>::Output {
let (a1, a2) = args;
self.build()(a1, a2)
}
}
impl<A: Add<B>, B: Add<A>> FnMut<(A, B)> for Builder {
extern "rust-call" fn call_mut(&mut self, args: (A, B)) -> <A as std::ops::Add<B>>::Output {
let (a1, a2) = args;
self.build()(a1, a2)
}
}
impl<A: Add<B>, B: Add<A>> FnOnce<(A, B)> for Builder {
type Output = <A as std::ops::Add<B>>::Output;
extern "rust-call" fn call_once(self, args: (A, B)) -> <A as std::ops::Add<B>>::Output {
let (a1, a2) = args;
self.build()(a1, a2)
}
}
fn test<F, I: Debug>(gen: F) where F: Fn(Builder) -> I {
let b = Builder;
println!("{:?}", gen(b));
}
fn main() {
test(|builder| {
builder(10, 10);
builder(10.1, 10.0)
});
}
如前所述,不幸的是,调用在调用站点上是单色的,因此您不能传递通用函数,而只能传递通用函数的单色版本。
但是,您可以传递的是一个函数生成器:
use std::fmt::Debug;
struct Builder;
impl Builder {
fn build<I: Debug>(&self) -> fn(I) -> I {
fn input<I: Debug>(x: I) -> I { x }
input
}
}
fn test<F, T: Debug>(gen: F)
where F: Fn(Builder) -> T
{
let builder = Builder;
println!("{:?}", gen(builder));
}
fn main() {
test(|builder| {
builder.build()(10);
builder.build()(10.0)
});
}
在Builder
能够产生的实例input
上的需求。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句