Rust实现merge-sorted迭代器

时间:2014-04-13 04:31:41

标签: iterator rust

我试图实现一个合并两个已排序迭代器的迭代器。我正在运行从结构中发布借用字段。

如何避免此错误?我尝试使用借用的引用,但这似乎没有帮助,因为最终我需要移动a_item和b_item的值。

use std::num::Saturating;

pub struct MergeSorted<A, T> {
    a: T,
    b: T,
    a_item: Option<A>,
    b_item: Option<A>,
}

impl<A: Ord, T: Iterator<A>> Iterator<A> for MergeSorted<A, T> {
    #[inline]
    fn next(&mut self) -> Option<A> {

        match (self.a_item, self.b_item) {
            (None, None) => None,

            (None, Some(y)) => {
                let result = self.b_item;
                self.b_item = None;
                return result;
            }

            (Some(x), None) => {
                let result = self.a_item;
                self.a_item = self.a.next();
                result
            }

            (Some(x), Some(y)) => {
                if x < y {
                    let result = self.a_item;
                    self.a_item = self.a.next();
                    result
                } else {
                    let result = self.b_item;
                    self.b_item = self.b.next();
                    result
                }
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        // stub
        (10, Some(100))
    }
}

以下是具体错误,对于self.a_item和self.b_item的所有用法都会重复此操作。

error: cannot move out of dereference of `&mut`-pointer
       match (self.a_item, self.b_item) {
              ^~~~~~~~~~~

1 个答案:

答案 0 :(得分:5)

第一个问题是这种模式:

let result = self.b_item;
self.b_item = None;
return result;

在第一行之后和第二行self.b_item移出之前,在self中形成一个“洞”(即使我们忘记了self是一个借来的指针,你可以不要离开它。这是不允许的。为了表达这种模式,std::mem中有一个特殊功能,称为replace

第二个主要问题是A不可隐式复制,因此当您尝试匹配类型Option<A>的值时,这些值会被移出,但会从{ {1}}指针被禁止。解决这个问题的唯一方法是匹配引用。但是那时你应该小心,因为借用规则只允许你一次有单一的可变借款。因此,您必须使用模式绑定通过匹配语句组织一种对&/&mutself.a_item的引用“流”。

以下代码编译。您还可以使用self.b_item调用直接替换result正文中的Some()变量和match用法,但我认为分隔值选择和mem::replace()调用make代码清理器。另外,我在上一个mem::replace()手臂中无法使用Some(x)Some(y)模式,因为引用本身已移至matcha_item

b_item