无法一次多次借用一个可变的迭代器 [英] Unable to borrow an iterator as mutable more than once at a time

查看:23
本文介绍了无法一次多次借用一个可变的迭代器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用 Rust 编写一个简单的标记器,但遇到了麻烦.为了这个问题,我稍微简化了代码:

I'm writing a simple tokenizer in Rust but I'm having trouble. I've simplified the code a bit for the sake of this question:

use std::iter::Peekable;
use std::str::Chars;

struct Example<'a> {
    it: Peekable<Chars<'a>>,
}

impl<'a> Example<'a> {
    fn tokenize_string(&mut self) {
        loop {
            match self.it.peek() {
                None => break,
                Some(_x) => self.it.next(),
            };
        }
    }
}

我得到的错误是:

error[E0499]: cannot borrow `self.it` as mutable more than once at a time
  --> src/main.rs:13:29
   |
11 |             match self.it.peek() {
   |                   ------- first mutable borrow occurs here
12 |                 None => break,
13 |                 Some(_x) => self.it.next(),
   |                             ^^^^^^^ second mutable borrow occurs here
14 |             };
   |             - first borrow ends here

我已经能够通过创建迭代器的副本并在其上调用 peek() 来解决这个问题:

I've been able to work around this by creating a copy of the iterator and calling peek() on that:

fn tokenize_string(&mut self) {
    loop {
        let mut iterator = self.it.clone();
        match iterator.peek() {
            None => break,
            Some(_x) => self.it.next(),
        };
    }
}

这是最好的方法吗?这似乎有点hack-ish.

Is this the best way to do this? It seems a little hack-ish.

推荐答案

由于您使用的是 str::chars(),并且 char复制,你可以解引用得到一个char而不是&char.:

Since you're working with str::chars(), and char is Copy, you can dereference to get a char instead of &char. :

fn tokenize_string(&mut self) {
    loop {
        let r = self.it.peek().cloned();
        let n = match r {
            Some(_) => self.it.next(),
            None => break,
        };
        // whatever
    }
}

如果你只想检查迭代器是否返回了一些东西,使用is_some():

If you just want to check if the iterator has returned something, use is_some():

let r = self.it.peek().is_some();
if r { ... } else { ... }

但是,总的来说,我不确定是否可以在没有非词法生命周期的情况下以这种方式完全正确.您将需要放置检查迭代器状态的代码和基于具有作用域的状态与迭代器一起工作的代码,如下所示:

In general, however, I'm not sure if it is possible exactly in this manner without non-lexical lifetimes. You will need to put the code which checks iterator state and the code which works with the iterator based on the state with scopes, something like this:

let r = {
    // work with self.it
};
if r { ... } else { ... }

这里对 self 的任何引用都不能转义 r 中的词法块,因此在包含引用的值上没有直接的 match进入self.在HashMap 的 Rust 借用是否超出了它的范围? 中有更多的例子可以解决这个问题.

Here any references into self must not escape the lexical block in r, so there is no direct match on a value which contains references into self. There's further examples of working around this in Rust borrow of a HashMap lasts beyond the scope it's in?.

这篇关于无法一次多次借用一个可变的迭代器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆