有什么方法可以向编译器暗示我不关心None
或者使用某种默认值?
您可以实现自己的非通用值作为默认值。首先,我们假设print_iter
不接受Option<T>
,但是它自己的枚举:
enum PrintArg<T> {
Ignore,
Use(T),
}
fn print_iter<T: IntoIterator<Item = i32>>(v: PrintArg<T>) {
if let PrintArg::Use(v) = v {
for e in v {
println!("{}", e);
}
}
}
这还没有解决问题,因为如果你通过了PrintArg::Ignore
to print_iter()
,您回到了第一个方 - 编译器无法推断出T
。但用你自己的类型,你可以轻松改变print_iter
接受任何可能的事情转换的 into PrintArg
:
fn print_iter<T, V>(v: T)
where
T: Into<PrintArg<V>>,
V: IntoIterator<Item = i32>,
{
if let PrintArg::Use(v) = v.into() {
for e in v {
println!("{}", e);
}
}
}
通过此修改,您可以创建一个虚拟的非泛型Ignore
重视并使用From特征来定义其转换为PrintArg::Ignore<T>
with T
您的选择 - 例如:
struct Ignore;
impl From<Ignore> for PrintArg<Vec<i32>> {
fn from(_v: Ignore) -> Self {
PrintArg::Ignore
}
}
As Ignore
是非通用的,它的使用不需要(或接受)<T>
。虽然我们确实必须发明一种类型PrintArg<T>
in the From
特征实现,我们从不构造它,所以我们选择哪一个并不重要,只要它满足IntoIterator
bound.
当然,您仍然希望能够调用print_iter()
with Some(...)
,所以您还需要定义一个转换Option<T>
to PrintArg<T>
:
impl<T> From<Option<T>> for PrintArg<T> {
fn from(v: Option<T>) -> Self {
match v {
Some(v) => PrintArg::Use(v),
None => PrintArg::Ignore,
}
}
}
有了这些,您的 API 就干净了,允许main()
看起来像这样(操场):
fn main() {
let v = vec![1i32, 2, 3];
print_iter(Some(v));
print_iter(Ignore);
}