如何使用静态/动态调度实现iter方法?

时间:2015-07-22 13:18:03

标签: rust dispatch

我需要实现方法iter,它返回实现特征Iterator<Item = char>的东西。但返回值将是不同的实现,具体取决于枚举变体。

这样的事情:

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()返回一个实现Iterator<Item=char>的结构。

mergeinterleaveitertools方法,分别返回MergeAscendInterleave(两者都实现Iterator<Item=char>

  1. 如何使用静态调度实现这样的方案?
  2. 如果无法进行静态调度,如何使用动态调度实现这样的方案?

1 个答案:

答案 0 :(得分:3)

使用静态调度无法做到这一点。在未装箱的抽象返回类型上有tracking RFC issue,但Rust还没有(我不确定它是否可以涵盖返回不同类型的用例)。因此,动态调度是可行的方法。

实际上,你非常接近。只需返回类型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()
        },
    }
}

这应该有用。