简单的回答是:你不能.至少它不会按你想要的方式工作.我认为展示这一点的最好方法是仔细观察,看看会发生什么,但一般的 idea 是Rust不支持函数重载.
在这个例子中,我们将实现FnOnce
,因为Fn
需要FnMut
,这需要FnOnce
.所以,如果我们把这些都分类,我们可以对其他功能特性进行分类.
首先,这是不稳定的,所以我们需要一些特性标志
#![feature(unboxed_closures, fn_traits)]
然后,让我们用impl
来做f64
:
impl FnOnce<(f64,)> for Clf {
type Output = i32;
extern "rust-call" fn call_once(self, args: (f64,)) -> i32 {
if args.0 > self.x {
1
} else {
0
}
}
}
Fn
个特征家族的参数是通过一个元组提供的,这就是(f64,)
语法;这是一个只有一个元素的元组.
这一切都很好,我们现在可以做到c(0.5)
,尽管在我们实现其他特征之前,它将消耗c
.
现在,让我们在Vec
秒内做同样的事情:
impl FnOnce<(Vec<f64>,)> for Clf {
type Output = Vec<i32>;
extern "rust-call" fn call_once(self, args: (Vec<f64>,)) -> Vec<i32> {
args.0
.iter()
.map(|&f| if f > self.x { 1 } else { 0 })
.collect()
}
}
在Rust 1.33 nightly岁之前,你不能直接拨打c(v)
甚至c(0.5)
(以前工作过);我们会得到一个关于函数类型未知的错误.基本上,这些版本的Rust不支持函数重载.但我们仍然可以使用fully qualified syntax调用函数,其中c(0.5)
变成FnOnce::call_once(c, (0.5,))
.
不知道你的大局,我想通过给Clf
个函数来解决这个问题,如下所示:
impl Clf {
fn classify(&self, val: f64) -> u32 {
if val > self.x {
1
} else {
0
}
}
fn classify_vec(&self, vals: Vec<f64>) -> Vec<u32> {
vals.into_iter().map(|v| self.classify(v)).collect()
}
}
然后你的用法示例就变成了
let c = Clf { x: 0 };
let v = vec![-1, 0.5, 1];
println!("{}", c.classify(0.5)); // prints 1
println!("{}", c.classify_vec(v)); // prints [0, 1, 1]
实际上,我想把第二个函数设为classify_slice
,把&[f64]
设为更一般的函数,然后你仍然可以通过引用Vec
来使用它:c.classify_slice(&v)
.