rust - How to implement iter method using static/dynamic dispatch? -


i need implement method iter, returns implements trait iterator<item = char>. return value different implementations, depending on enum variant.

something this:

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 struct implements iterator<item=char>.

merge , interleave itertools methods, return mergeascend , interleave respectively (both of them implement iterator<item=char>)

  1. how implement such scheme using static dispatch?
  2. if static dispatch not possible, how implement such scheme using dynamic dispatch?

it not possible using static dispatch. there tracking rfc issue on unboxed abstract return types, rust not there yet (and i'm not sure if cover use case of returning different types). therefore, dynamic dispatch way go.

you're pretty close, actually. make return type box<iterator<item=char>> , add more boxing:

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

this should work.


Comments

Popular posts from this blog

Fail to load namespace Spring Security http://www.springframework.org/security/tags -

sql - MySQL query optimization using coalesce -

unity3d - Unity local avoidance in user created world -