rust - 一个函数可以同时采用 IntoIterator和 IntoIterator<&T>?
问题描述
我想要一个带有两个参数的函数,这两个参数都可以变成Foo
. 问题是我想接受既是IntoIterator<Foo>
又是的东西IntoIterator<&Foo>
。重要Foo
的是Copy
,我可以从它的参考中廉价地创建一个拥有的副本。
我目前的解决方案是:
use std::borrow::Cow;
use std::iter::IntoIterator;
fn main() {
let foos = [Foo {}, Foo {}, Foo {}];
let references = || foos.iter();
let owned = || foos.iter().cloned();
bar(references(), references());
bar(references(), owned());
bar(owned(), references());
bar(owned(), owned());
}
#[derive(Copy, Clone)]
struct Foo {
// code ommitted here
}
impl<'a> From<Foo> for Cow<'a, Foo> {
fn from(foo: Foo) -> Self {
Self::Owned(foo)
}
}
impl<'a> From<&'a Foo> for Cow<'a, Foo> {
fn from(foo: &'a Foo) -> Self {
Self::Borrowed(foo)
}
}
fn bar<'a, AIter, A, BIter, B>(alpha_iter: AIter, beta_iter: BIter)
where
AIter: IntoIterator<Item=A>,
A: Into<Cow<'a, Foo>>,
BIter: IntoIterator<Item=B>,
B: Into<Cow<'a, Foo>>
{
for (alpha, beta) in alpha_iter.into_iter().zip(beta_iter.into_iter()) {
some_foo_specific_thing(*alpha.into(), *beta.into());
}
}
fn some_foo_specific_thing(alpha: Foo, beta: Foo) {
// code ommitted here
}
有没有办法在更少的行/没有的情况下做到这一点Cow
?
解决方案
首先,您不需要IntoIterator
在这里完全绑定。刚好够用Iterator<Item = Foo>
。
use std::borrow::Cow;
use std::iter::IntoIterator;
fn main() {
let foos = [Foo {}, Foo {}, Foo {}];
let references = || foos.iter(); // it is iterator itself
let owned = || foos.iter().cloned(); // it is iterator itself
bar(references(), references());
bar(references(), owned());
bar(owned(), references());
bar(owned(), owned());
}
fn bar<'a, AIter, A, BIter, B>(alpha_iter: AIter, beta_iter: BIter)
where
AIter: Iterator<Item = A>,
A: Into<Cow<'a, Foo>>,
BIter: Iterator<Item = B>,
B: Into<Cow<'a, Foo>>
{
for (alpha, beta) in alpha_iter.zip(beta_iter) {
some_foo_specific_thing(*alpha.into(), *beta.into());
}
}
其次,我认为最好使用Borrow
trait:
fn bar<'a, AIter, A, BIter, B>(alpha_iter: AIter, beta_iter: BIter)
where
AIter: Iterator<Item = A>,
A: std::borrow::Borrow<Foo> + Copy,
BIter: Iterator<Item = B>,
B: std::borrow::Borrow<Foo> + Copy,
{
let alpha_iter = alpha_iter.map(|item| *item.borrow()); // here we get a reference to an item and then make a copy to own it
let beta_iter = beta_iter.map(|item| *item.borrow()); // here we get a reference to an item and then make a copy to own it
for (alpha, beta) in alpha_iter.zip(beta_iter) {
some_foo_specific_thing(alpha, beta);
}
}
推荐阅读
- wordpress - Linkedin 后检查员无法显示我的网页的预览
- asp.net - 如何使用 Nuget 的库?
- postgresql - Pgadmin4 SQL 创建表查询在 ubuntu 18.04 上的 Postgresql 命令行中不起作用
- jquery - 使用 jquery 查找和删除 div 中的文本
- android - 使用 Android Studio 调试 C++ 库
- tensorflow - 如何重用 rnn 单元进行推理
- nlp - cTakes 在“MaxentParserWrapper - 开始处理:.DS_Strore”上花费了很长时间
- google-cloud-platform - VPC 流日志:VPC 流日志的成本是多少?
- java - 匹配直到遇到 0 或 1
- javascript - Javascript If 语句然后继续