【问题标题】:How can a function conditionally fall back to a trait if another trait is implemented or not?如果实现了另一个特征,函数如何有条件地回退到一个特征?
【发布时间】:2018-12-16 13:23:05
【问题描述】:

我正在建立a library for generating the minimum perfect hash from a set of keys。这个想法是在线索引键而不将完整的数据集存储在内存中。根据用户要求,skip_next() 可能不可用,我想回退到使用next()。虽然根据迭代器的速度可能会更慢,但它为普通用户简化了操作。

我的想法是有选择地迭代迭代器生成的所有元素。此代码运行良好,但需要用户实现特征FastIteration

#[derive(Debug)]
struct Pixel {
    r: Vec<i8>,
    g: Vec<i8>,
    b: Vec<i8>,
}

#[derive(Debug)]
struct Node {
    r: i8,
    g: i8,
    b: i8,
}

struct PixelIterator<'a> {
    pixel: &'a Pixel,
    index: usize,
}

impl<'a> IntoIterator for &'a Pixel {
    type Item = Node;
    type IntoIter = PixelIterator<'a>;

    fn into_iter(self) -> Self::IntoIter {
        println!("Into &");
        PixelIterator {
            pixel: self,
            index: 0,
        }
    }
}

impl<'a> Iterator for PixelIterator<'a> {
    type Item = Node;
    fn next(&mut self) -> Option<Node> {
        println!("next &");
        let result = match self.index {
            0 | 1 | 2 | 3 => Node {
                r: self.pixel.r[self.index],
                g: self.pixel.g[self.index],
                b: self.pixel.b[self.index],
            },
            _ => return None,
        };
        self.index += 1;
        Some(result)
    }
}

trait FastIteration {
    fn skip_next(&mut self);
}

impl<'a> FastIteration for PixelIterator<'a> {
    fn skip_next(&mut self) {
        self.index += 1;
    }
}

fn main() {
    let p1 = Pixel {
        r: vec![11, 21, 31, 41],
        g: vec![12, 22, 32, 42],
        b: vec![13, 23, 33, 43],
    };

    let mut index = 0;
    let mut it = p1.into_iter();
    loop {
        if index == p1.r.len() {
            break;
        }

        if index == 1 {
            it.skip_next()
        } else {
            let val = it.next();
            println!("{:?}", val);
        }
        index += 1;
    }
}

如何根据特征FastIteration 是否实现,使上述程序回退到使用普通的next() 而不是skip_next()

fn fast_iterate<I>(objects: I)
    where I: IntoIter + FastIteration { // should use skip_next() };

fn slow_iterate<I>(objects: I)
    where I: IntoIter { // should NOT use skip_next(), use next() };

如上所述,一个人总是可以写两个独立的impl,但是否可以合二为一?

这个问题建立在:

【问题讨论】:

    标签: iterator rust


    【解决方案1】:

    您正在寻找不稳定功能专业化

    #![feature(specialization)]
    
    #[derive(Debug)]
    struct Example(u8);
    
    impl Iterator for Example {
        type Item = u8;
        fn next(&mut self) -> Option<u8> {
            let v = self.0;
            if v > 10 {
                None
            } else {
                self.0 += 1;
                Some(v)
            }
        }
    }
    
    trait FastIterator: Iterator {
        fn skip_next(&mut self);
    }
    
    impl<I: Iterator> FastIterator for I {
        default fn skip_next(&mut self) {
            println!("step");
            self.next();
        }
    }
    
    impl FastIterator for Example {
        fn skip_next(&mut self) {
            println!("skip");
            self.0 += 1;
        }
    }
    
    fn main() {
        let mut ex = Example(0);
        ex.skip_next();
    
        let mut r = 0..10;
        r.skip_next();
    }
    

    【讨论】:

    • 感谢 @Shepmaster 重新格式化问题并快速回答!
    猜你喜欢
    • 1970-01-01
    • 2015-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-20
    相关资源
    最近更新 更多