在Rust中捕获外部作用域作为结构域的闭包

h7wcgrx3  于 2022-12-19  发布在  其他
关注(0)|答案(1)|浏览(111)

我是Rust的新手,我正在尝试在其中创建组合子解析器。下面是代码:

enum Parser<T: Copy + Eq> {
    Ok,
    Eof,
    Satisfy { predicate:  Box<dyn Fn(&T) -> bool> },
    Element { elem : T }
}

impl<T: Copy + Eq> Parser<T> {
    fn parse<'a, P>(&self, input: &'a [T]) -> Option<(&'a [T], P)>
    where
        P: Default,
        T: Into<P>
    {
        match self {
            Parser::Ok => Some((input, P::default())),
            Parser::Eof => match input {
                [] => None,
                _ => Some((input, P::default())),
            },
            Parser::Satisfy { predicate } => match input {
                [] => None,
                [x, rest @ ..] => {
                    if predicate(x) {
                        Some((rest, T::into(*x)))
                    } else {
                        None
                    }
                }
            },
            Parser::Element { elem } => {
                let to_match = *elem;
                Parser::Satisfy { predicate: Box::new(move|x| *x == to_match) }.parse(input)
            }
        }
    }
}

Parser::Ok、Parser::Eof和Parser::Satisfy工作正常,但我在实现Parser::Element(必须仅精确到元素)时遇到了困难。我想通过创建Parser::Satisfy实现方法解析,并在参数x和给定elem之间使用eq predicate 。但我遇到了此错误:

error[E0310]: the parameter type `T` may not live long enough
  --> src/lib.rs:32:46
   |
32 |                 Parser::Satisfy { predicate: Box::new(move|x| *x == to_match) }.parse(input)
   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
   |
help: consider adding an explicit lifetime bound...
   |
8  | impl<T: Copy + Eq + 'static> Parser<T> {
   |                   +++++++++

我觉得生命存在一些问题,但我不知道如何解决它。

biswetbf

biswetbf1#

dyn Trait包含一些东西,这些东西可能有生存期,因此dyn Trait也有生存期。
这个生存期和函数的生存期一样,可以省略。完整的规则有些复杂,但是在ADT中,生存期被假定为'static。您可以使用dyn Trait + 'lifetime指定另一个生存期。
因此,枚举中的Box<dyn Fn(&T) -> bool>实际上是Box<dyn Fn(&T) -> bool + 'static>
但是问题是你分配给它的函数捕获to_match,类型为T,并且类型T可能包含非'static的生存期,例如,它可能包含&'non_static str,这就是错误。
这有两种可能的解决方案。
要么接受这一点,并要求T'static

impl<T: Copy + Eq + 'static> Parser<T> {

或者允许函数的生存期为非'static

enum Parser<'a, T: Copy + Eq> {
    Ok,
    Eof,
    Satisfy { predicate:  Box<dyn Fn(&T) -> bool + 'a> },
    Element { elem : T }
}

impl<T: Copy + Eq> Parser<'_, T> {

相关问题