【问题标题】:Pull struct out of associated type returned by iterator从迭代器返回的关联类型中拉出结构
【发布时间】:2021-11-25 09:28:56
【问题描述】:

我正在 rust 中实现一个双链表。我创建了一个运行良好的迭代器。

#[derive(Clone, Debug)]
pub struct LLCursor<T: Copy> {
    pub cur: Option<Rc<RefCell<Node<T>>>>,
}

impl<T> IntoIterator for List<T>
where
    T: Clone + Copy,
{
    type Item = Rc<RefCell<Node<T>>>;
    type IntoIter = LLCursor<T>;

    fn into_iter(self) -> Self::IntoIter {
        LLCursor {
            cur: self.head.clone(),
        }
    }
}

impl<T> Iterator for LLCursor<T>
where
    T: Copy,
{
    type Item = Rc<RefCell<Node<T>>>;

    fn next(&mut self) -> Option<Rc<RefCell<Node<T>>>> {
        match self.cur.clone() {
            Some(node) => {
                self.cur = node.borrow().next.clone();
                Some(node)
            }
            None => None,
        }
    }
}

我想创建一个函数,可以在迭代时访问链表的节点内容。像这样的:

pub fn print(self)
where
    List<T>: IntoIterator,
    <List<T> as IntoIterator>::Item: std::fmt::Debug,
{
    for i in self {
        println!("{:?}", Some(i.borrow().clone().item));
    }
}

错误:

error[E0599]: no method named `borrow` found for associated type `<List<T> as IntoIterator>::Item` in the current scope
   --> src/list.rs:90:51
    |
90  |             println!("{:?}", i.borrow().clone().item);
    |                                ^^^^^^ method not found in `<List<T> as IntoIterator>::Item`
    |
    = help: items from traits can only be used if the trait is in scope
    = note: the following trait is implemented but not in scope; perhaps add a `use` for it:
            `use std::borrow::Borrow;`

我知道在这种情况下i&lt;List&lt;T&gt; as IntoIterator&gt;::Item 类型。我是 rust 新手,所以我看不出迭代器以这种方式返回关联类型有什么用处。我希望i 的类型为Option&lt;Rc&lt;RefCell&lt;Node&lt;T&gt;&gt;&gt;&gt;。有没有办法可以将其从关联类型中提取出来,以便能够访问每个单独节点的元素?

【问题讨论】:

标签: rust iterator associated-types


【解决方案1】:

没有一个迭代器代码实际上需要T: Copy,我建议你删除它,因为它混淆了你的问题。那么,既然你知道&lt;List&lt;T&gt; as IntoIterator&gt;::Item其实就是T,那你就可以直接使用了:

pub fn print(self) where T: Debug {
    for i in self {
        println!("{:?}", i.borrow().item);
    }
}

打印时我还删除了.clone(),因为它是不必要的,并且避免了T: Clone 约束。在playground 上查看它。


您得到错误的原因是因为限制List&lt;T&gt;: IntoIteratorItem: Debug 并不意味着ItemRc&lt;RefCell&lt;_&gt;&gt;。您将需要一个额外的约束 T: Copy 来推断正确的 IntoIterator 实现。就您演示的代码而言,不存在其他实现,但理论上存在一个不冲突的实现可能,并且编译器不会进行猜测。

作为旁注,限制Self 类型(此处明确为List&lt;T&gt;)非常罕见,除非在特征中,因为您通常知道Self 需要什么来满足这些限制,并且它更具描述性直接列出来。 (即,如果Self 需要是Clone,但你知道SelfClone,如果TClone,你会使用T: Clone 作为约束)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多