这里是生锈的初学者。我有一个使用两种类型的“二进制计算器”。
pub enum Bit { Off, On };
pub struct Binary([Bit; 64]);
忽略为他们实现的所有其他功能,我像这样使Binary
的运算符超载...
impl Add for Binary {
type Output = Binary;
/// Basic implementation of full addition circuit
fn add(self, other: Binary) -> Binary {
...
}
}
... Div, Sub, and Mul
...,其中每个运算符都使用传递给他们的Binary
。然后,我可以定义一组公共函数,这些函数负责转换,调用和打印我想要的所有内容...
pub fn add(x: i64, y: i64) -> Calc {
execute(Binary::add, x, y)
}
pub fn subtract(x: i64, y: i64) -> Calc {
execute(Binary::sub, x, y)
}
...
fn execute(f: fn(Binary, Binary) -> Binary, x: i64, y: i64) -> Calc {
let bx = Binary::from_int(x);
println!("{:?}\n{}\n", bx, x);
let by = Binary::from_int(y);
println!("{:?}\n{}\n", by, y);
let result = f(bx, by);
println!("{:?}", result);
result.to_int()
}
这有效,但是操作消耗了Binary
,而这并不是我真正想要的。因此,我改为使用引用来实现特征...
impl<'a, 'b> Add<&'b Binary> for &'a Binary {
type Output = Binary;
/// Basic implementation of full addition circuit
fn add(self, other: &'b Binary) -> Binary {
...
}
}
但是,现在,我无法像以前一样弄清楚如何将这些函数传递给execute
。例如,execute(Binary::div, x, y)
出现以下错误。
error[E0277]: cannot divide `types::binary::Binary` by `_`
--> src/lib.rs:20:13
|
20 | execute(Binary::div, x, y)
| ^^^^^^^^^^^ no implementation for `types::binary::Binary / _`
|
= help: the trait `std::ops::Div<_>` is not implemented for
`types::binary::Binary`
如何通过生命周期传递特定的实现?我假设我也需要更新execute
的签名,例如...
fn execute<'a, 'b>(f: fn(&'a Binary, &'b Binary) -> Binary, ...
但我也发现...
error[E0308]: mismatched types
--> src/lib.rs:20:13
|
20 | execute(Binary::div, x, y)
| ^^^^^^^^^^^ expected reference, found struct `types::binary::Binary`
|
= note: expected type `fn(&types::binary::Binary, &types::binary::Binary) -> types::binary::Binary`
found type `fn(types::binary::Binary, _) -> <types::binary::Binary as std::ops::Div<_>>::Output {<types::binary::Binary as std::ops::Div<_>>::div}`
作为一个完整的初学者,我能够跟踪所有使我到达“工作”点(操作消耗了值)的错误消息,但是现在,我觉得我有点不合时宜了。 / p>
答案 0 :(得分:1)
我为加法做了一个示例性的实现(我对execute
的返回类型做了一些假设,而其他假设,如果我的假设是错误的,则必须对此进行调整):
use std::ops::Add;
#[derive(Debug)]
pub enum Bit { Off, On }
#[derive(Debug)]
pub struct Binary([Bit; 32]);
impl Binary {
fn to_int(&self) -> i64 {unimplemented!()}
fn from_int(n: i64) -> Self {unimplemented!()}
}
impl<'a, 'b> Add<&'b Binary> for &'a Binary {
type Output = Binary;
fn add(self, other: &'b Binary) -> Binary {
unimplemented!()
}
}
pub fn add(x: i64, y: i64) -> i64 {
execute(|a, b| a+b, x, y)
}
fn execute(f: fn(&Binary, &Binary) -> Binary, x: i64, y: i64) -> i64 {
let bx = Binary::from_int(x);
println!("{:?}\n{}\n", bx, x);
let by = Binary::from_int(y);
println!("{:?}\n{}\n", by, y);
let result = f(&bx, &by);
println!("{:?}", result);
result.to_int()
}
请注意,在execute
中,您必须致电f(&bx, &by)
(即借用而不是消费)。
但是:我想知道为什么您选择使用fn(&Binary, &Binary) -> Binary
作为参数类型,而不是使execute
成为F
的泛型,从而约束F
成为可调用对象:
fn execute<F>(f: F, x: i64, y: i64) -> i64
where
F: Fn(&Binary, &Binary) -> Binary,
{
let bx = Binary::from_int(x);
println!("{:?}\n{}\n", bx, x);
let by = Binary::from_int(y);
println!("{:?}\n{}\n", by, y);
let result = f(&bx, &by);
println!("{:?}", result);
result.to_int()
}
这样,您会更加灵活(例如,可以传递闭包来捕获变量范围内的变量)。