问题描述
我似乎在使用 Rust 时遇到了问题,当然希望得到一些帮助。
我有一个实现 Iterator trait 的自定义 struct
,以及一个单独的 struct
(也是一个迭代器),我希望能够包装任何东西它表现为一个可迭代的。其中一些似乎可以通过泛型实现,但是,当在包装器中获得特定的 struct
时,事情似乎会走向一边。
我的主要目标是接受任何返回 Option<char>
的可迭代对象,并执行一些解析/字符集合。
src/main.rs
#!/usr/bin/env rust
struct IteratorHolder<I,T>
where
I: Iterator<Item = T>
{
iter: I,}
impl<I,T> Iterator for IteratorHolder<I,T>
where
I: Iterator<Item = T>
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
impl<I,T> IteratorHolder<I,T>
where
I: Iterator<Item = T>
{
#[allow(dead_code)]
fn new(iter: I) -> Self {
Self { iter }
}
}
impl<I,T> From<I> for IteratorHolder<I,T>
where
I: Iterator<Item = T>,{
fn from(iter: I) -> Self {
Self { iter }
}
}
// ============================================================================
struct CustomIterator {
data: Option<(usize,String)>
}
impl CustomIterator {
#[allow(dead_code)]
fn new<S>(string: S) -> Self
where
S: Into<String>
{
let string: String = string.into();
let data = Some((0,string));
Self { data }
}
}
impl Iterator for CustomIterator {
type Item = char;
fn next(&mut self) -> Option<Self::Item> {
if let Some((index,string)) = self.data.take() {
let mut iter = string.get(index..).unwrap().char_indices();
if let Some((_,c)) = iter.next() {
self.data = iter.next().map(|(i,_)| (index + i,string));
return Some(c);
}
}
None
}
}
// ============================================================================
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn map() {
let v = vec![1,2,3];
let m = v.into_iter().map(|n| n * 2);
let mut i = IteratorHolder::new(m);
assert_eq!(i.next(),Some(2));
}
#[test]
fn chars() {
let s = String::from("abc");
let c = s.chars();
let mut i = IteratorHolder::new(c);
assert_eq!(i.next(),Some('a'));
}
#[test]
fn custom_iterator() {
let c = CustomIterator::new("zxc");
let mut i = IteratorHolder::new(c);
assert_eq!(i.next(),Some('z'));
}
#[test]
fn from_iter() {
let c = CustomIterator::new("zxc");
let mut i = IteratorHolder::from(c);
assert_eq!(i.next(),Some('z'));
}
}
最重要的是似乎没有错误
我发现奇怪的是,当具体使用 From
实现时,会出现各种类型错误。
例如,我在 FromStr
上实现 IteratorHolder
时会产生 E0053
错误...
方法 from_str
具有不兼容的 trait 预期 fn 指针类型
fn(&str) -> std::result::Result<IteratorHolder<I,T>,_>
找到
fn 指针 fn(&str) -> std::result::Result<IteratorHolder<CustomIterator,char>,_>
[E0053]
src/main.rs
(剪辑)
use std::str::FromStr;
use std::num::ParseIntError;
impl<I,T> FromStr for IteratorHolder<I,{
type Err = ParseIntError;
fn from_str(s: &str) -> Result<IteratorHolder<CustomIterator,Self::Err> {
let iter = CustomIterator::new(s);
let hold = IteratorHolder { iter };
Ok(hold)
}
}
... 更通用会产生 E0308
错误...
不匹配的类型预期类型参数 I
发现结构 CustomIterator
[E0308]
impl<I,{
type Err = ParseIntError;
fn from_str(s: &str) -> Result<Self,Self::Err> {
let iter = CustomIterator::new(s);
let hold = Self { iter };
Ok(hold)
}
}
基本上我正在面对如何让IteratorHolder
更加自给自足,关于From
em> 实现。我的主要目标是拥有一个类似于 IteratorHolder
的解析器,它可以从迭代器中读取字符,而不管这些字符来自哪里;例如。文件、流、字符串。等
解决方法
正如@Aplet123 所提到的,您声称为包含 any 迭代器的 FromStr
实现 IteratorHolder
,但是您实际上只想为 IteratorHolder<CustomIterator>
实现它.这是一个工作版本,清理了一点,更惯用了(特别是:我删除了 T
因为它是多余的,它已经作为 I::Item
存在):
use std::num::ParseIntError;
use std::str::FromStr;
struct IteratorHolder<I> {
iter: I,}
impl<I: Iterator> Iterator for IteratorHolder<I> {
type Item = I::Item;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
}
impl<I: Iterator> IteratorHolder<I> {
#[allow(dead_code)]
fn new(iter: I) -> Self {
Self { iter }
}
}
impl<I: Iterator> From<I> for IteratorHolder<I> {
fn from(iter: I) -> Self {
Self::new(iter)
}
}
// ============================================================================
struct CustomIterator {
data: Option<(usize,String)>,}
impl CustomIterator {
#[allow(dead_code)]
fn new<S: Into<String>>(string: S) -> Self {
Self {
data: Some((0,string.into())),}
}
}
impl Iterator for CustomIterator {
type Item = char;
fn next(&mut self) -> Option<Self::Item> {
if let Some((index,string)) = self.data.take() {
let mut iter = string.get(index..).unwrap().char_indices();
if let Some((_,c)) = iter.next() {
self.data = iter.next().map(|(i,_)| (index + i,string));
return Some(c);
}
}
None
}
}
impl FromStr for IteratorHolder<CustomIterator> {
type Err = ParseIntError;
fn from_str(s: &str) -> Result<Self,Self::Err> {
Ok(IteratorHolder {
iter: CustomIterator::new(s),})
}
}