How to implement iter method using static / dynamic dispatch?

I need to implement a method iterthat returns what implements the attribute Iterator<Item = char>. But the return value will have different implementations, depending on the enumeration option.

Something like that:

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()returns a structure that implements Iterator<Item=char>.

mergeand there interleaveare itertoolsmethods that return MergeAscendand interleaveaccordingly (both of them implement Iterator<Item=char>)

  • How to implement such a scheme using static dispatch?
  • If static sending is not possible, how to implement such a scheme using dynamic sending?
+4
source share
1 answer

, . RFC- , 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()
        },
    }
}

.

+3

Source: https://habr.com/ru/post/1599103/


All Articles