在 Rust 中,在需要引用 self 的结构体方法中使用闭包作为 while 循环条件

问题描述 投票:0回答:1

我有一个简单的结构

Parser

pub struct Parser {
    pos: usize,
    input: String,
}

我正在尝试构建一个 Markdown 解析器,并且有一个方法

parse_md_line
包含一个 while 循环,我试图根据
delimiter

使 while 循环的条件动态化
pub fn parse_md_line(&mut self, delimiter: Option<char>) -> String {
    let mut result = String::new();

    let mut cond: Box<dyn Fn() -> bool> = Box::new(|| {
        return self.pos < self.input.len()
            && (self.next_char() != '\n' || utils::is_whitespace(self.next_char()));
    });

    if delimiter.is_some() {
        cond = Box::new(|| {
            return self.pos < self.input.len() && self.next_char() != delimiter.unwrap();
        });
    }

    while cond() {
        let normal_text = self.parse_alpha_numeric(true); // this mutates `self`
        .....
    }
 
  result
 }

while循环的内部工作是隐藏的,因为它们确实很重要,但它调用了一些方法,这会改变

self

此代码会引发

let normal_text = self.parse_alpha_numeric(true);
错误, **不能借用 *self 作为可变的,因为它也是借用为不可变的。

我了解该错误及其发生原因。但无法找到解决问题的方法。我敲了一下并尝试使用

RefCell
Rc
仍然没有用。

也许可以使用

RefCell
来完成,根据我的尝试,代码变得不必要的复杂。

有没有标准或更干净的方法来处理这样的事情。

rust borrow-checker interior-mutability
1个回答
0
投票

这里有多个问题:

  1. Fn
    无法修改它的环境,你可以将其更改为
    FnMut
    但是
  2. 您正在创建多个闭包,想要同时保存对 self 的可变引用,但
    &mut self
    只能保存一次
  3. 您想要修改
    self
    ,而闭包保留独占引用,但您无法创建对 self 的多个独占引用。

要解决这些问题,您可以将

self
作为闭包的参数,这样它就不需要捕获
self
,它也不需要是
FnMut
,因为您不需要修改任何环境更长:

pub fn parse_md_line(&mut self, delimiter: Option<char>)
    let cond: Box<dyn Fn(&mut Self) -> bool> = if delimiter.is_some() {
        Box::new(|this| {
            return this.pos < this.input.len() && this.next_char() != delimiter.unwrap();
        })
    } else {
        Box::new(|this| {
            return this.pos < this.input.len()
                && (this.next_char() != '\n' || this.next_char().is_whitespace());
        })
    };
    while cond(self) {
        let _normal_text = self.parse_alpha_numeric(true); // this mutates `self`
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.