我正在创建一种从迭代器中格式化数据的方法。为了允许链接,我试图通过泛型提供它作为Iterator的新方法:
trait ToSeparatedString {
fn to_separated_string(self, line_prefix: &str, separator: &str) -> String;
}
impl<T, I> ToSeparatedString for I
where
T: Display,
I: Iterator<Item = T> + Clone,
{
fn to_separated_string(self, line_prefix: &str, separator: &str) -> String {
let len = self.clone().count();
self.enumerate()
.map(|(i, line)| if i < len - 1 {
(line, separator)
} else {
(line, "")
})
.fold::<String, _>("".to_owned(), |acc, (line, line_end)| {
format!("{}{}{}{}", acc, line_prefix, line, line_end)
})
}
}
然后我在这里使用它:
#[derive(Debug)]
pub struct TransactionDocumentBuilder<'a> {
/// Currency Id.
pub currency: &'a str,
/// Document timestamp.
pub blockstamp: Blockstamp,
/// Transaction locktime (in seconds ?)
pub locktime: u64,
/// List of issuers.
pub issuers: Vec<ed25519::PublicKey>,
/// List of inputs.
pub inputs: Vec<Input>,
/// List of outputs.
pub outputs: Vec<Output>,
/// Transaction comment.
pub comment: &'a str,
}
impl<'a> DocumentBuilder<TransactionDocument> for TransactionDocumentBuilder<'a> {
fn build_with_signature(self, signature: ed25519::Signature) -> TransactionDocument {
TransactionDocument {
document: GenericDocumentBuilder::new(10, "Transaction", self.currency)
.with("Blockstamp", &self.blockstamp.to_string())
.with("Locktime", &self.locktime.to_string())
.with("Issuers", &self.issuers.iter().to_separated_string("", "\n"))
.with("Inputs", &self.inputs.iter()
.map(|input| input.source)
.to_separated_string("", " "))
// Iterate through each input unlocks
.with("Unlocks", &self.inputs.iter()
.enumerate()
.map(|(i, input)| {
input.unlocks.iter().to_separated_string(&i.to_string(), "\n")
})
.to_separated_string("", "\n")
)
// more fields
.build_with_signature(signature),
};
unimplemented!()
}
fn build_and_sign(self, _private_key: &ed25519::PrivateKey) -> TransactionDocument {
unimplemented!()
}
}
当我在.iter()
之后但在.map()
之后使用它时它会起作用,并说它没有实现。但是std::slice::Iter
和std::iter::Map
实现了Iterator<Item = T> + Clone
,那么问题出在哪里?
先谢谢你的帮助。
答案 0 :(得分:1)
您的问题的MCVE可以写成
vec![1,2,3].iter().map(|x| x).to_separated_string("", "")
以下假设你错了
Rust文档中
std::iter::Map
实施Iterator<Item = T> + Clone
std::iter::Map
的
impl<I, F> Clone for Map<I, F> where
F: Clone,
I: Clone,
当源迭代器Map
和函数Clone
的类型都实现I
时, F
实现Clone
。
不幸的是,在当前稳定的Rust版本1.22.1中,闭包没有实现Clone
。该功能在功能门clone_closures
下的夜间Rust中可用。 Playground link
您也可以通过重写Clone
来删除to_separated_string
的要求
fn to_separated_string(self, line_prefix: &str, separator: &str) -> String {
self.fold((true, "".to_string()), |(first, acc), line| {
(
false,
format!(
"{}{}{}{}",
acc,
if first { "" } else { separator },
line_prefix,
line
),
)
}).1
}