如何使用 static/dynamic dispatch 实现 iter 方法?
How to implement iter method using static/dynamic dispatch?
我需要实现方法 iter
,它 return 是实现特征 Iterator<Item = char>
的东西。但是 return 值将是不同的实现,具体取决于枚举变体。
像这样:
pub enum Class {
SingleChar(char),
Range(Range),
And(Vec<Class>),
Or(Vec<Class>),
}
impl Class {
pub fn iter(&self) -> Iterator<Item = char> {
match *self {
Class::SingleChar(c) => vec![c],
Class::Range(ref range) => range.iter(),
Class::And(ref classes) => {
let iter: Option<_> = classes.iter().fold(None, |iter, &class| {
match iter {
None => Some(class.iter()),
Some(iter) => Some(iter.merge(class.iter())),
}
});
Box::new(iter.unwrap())
},
Class::Or(ref classes) => {
let iter: Option<_> = classes.iter().fold(None, |iter, &class| {
match iter {
None => Some(class.iter()),
Some(iter) => Some(iter.interleave(class.iter())),
}
});
Box::new(iter.unwrap())
},
}
}
}
range.iter()
return 是一个实现 Iterator<Item=char>
.
的结构
merge
和interleave
是itertools
方法,分别是returnMergeAscend
和Interleave
(它们都实现了Iterator<Item=char>
)
- 如何使用静态调度实现这样的方案?
- 如果静态调度不可行,如何使用动态调度实现这样的方案?
无法使用静态分派来完成。在未装箱的抽象 return 类型上有一个 tracking RFC issue,但 Rust 还没有(我不确定它是否可以涵盖 returning 不同类型的用例)。因此,动态调度是可行的方法。
实际上,你已经很接近了。只需让 return 键入 Box<Iterator<Item=char>>
并添加更多装箱:
pub fn iter(&self) -> Box<Iterator<Item=char>> {
match *self {
Class::SingleChar(c) => Box::new(Some(c).into_iter()),
Class::Range(ref range) => Box::new(range.iter()),
Class::And(ref classes) => {
let iter: Option<_> = classes.iter().fold(None, |iter, &class| {
match iter {
None => Some(Box::new(class.iter())),
Some(iter) => Some(Box::new(iter.merge(class.iter()))),
}
});
iter.unwrap()
},
Class::Or(ref classes) => {
let iter: Option<_> = classes.iter().fold(None, |iter, &class| {
match iter {
None => Some(Box::new(class.iter())),
Some(iter) => Some(Box::new(iter.interleave(class.iter()))),
}
});
iter.unwrap()
},
}
}
这应该有效。
我需要实现方法 iter
,它 return 是实现特征 Iterator<Item = char>
的东西。但是 return 值将是不同的实现,具体取决于枚举变体。
像这样:
pub enum Class {
SingleChar(char),
Range(Range),
And(Vec<Class>),
Or(Vec<Class>),
}
impl Class {
pub fn iter(&self) -> Iterator<Item = char> {
match *self {
Class::SingleChar(c) => vec![c],
Class::Range(ref range) => range.iter(),
Class::And(ref classes) => {
let iter: Option<_> = classes.iter().fold(None, |iter, &class| {
match iter {
None => Some(class.iter()),
Some(iter) => Some(iter.merge(class.iter())),
}
});
Box::new(iter.unwrap())
},
Class::Or(ref classes) => {
let iter: Option<_> = classes.iter().fold(None, |iter, &class| {
match iter {
None => Some(class.iter()),
Some(iter) => Some(iter.interleave(class.iter())),
}
});
Box::new(iter.unwrap())
},
}
}
}
range.iter()
return 是一个实现 Iterator<Item=char>
.
merge
和interleave
是itertools
方法,分别是returnMergeAscend
和Interleave
(它们都实现了Iterator<Item=char>
)
- 如何使用静态调度实现这样的方案?
- 如果静态调度不可行,如何使用动态调度实现这样的方案?
无法使用静态分派来完成。在未装箱的抽象 return 类型上有一个 tracking RFC issue,但 Rust 还没有(我不确定它是否可以涵盖 returning 不同类型的用例)。因此,动态调度是可行的方法。
实际上,你已经很接近了。只需让 return 键入 Box<Iterator<Item=char>>
并添加更多装箱:
pub fn iter(&self) -> Box<Iterator<Item=char>> {
match *self {
Class::SingleChar(c) => Box::new(Some(c).into_iter()),
Class::Range(ref range) => Box::new(range.iter()),
Class::And(ref classes) => {
let iter: Option<_> = classes.iter().fold(None, |iter, &class| {
match iter {
None => Some(Box::new(class.iter())),
Some(iter) => Some(Box::new(iter.merge(class.iter()))),
}
});
iter.unwrap()
},
Class::Or(ref classes) => {
let iter: Option<_> = classes.iter().fold(None, |iter, &class| {
match iter {
None => Some(Box::new(class.iter())),
Some(iter) => Some(Box::new(iter.interleave(class.iter()))),
}
});
iter.unwrap()
},
}
}
这应该有效。