Rust函数签名和未成年人

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

要学习Rust,我正在编写一个解析器组合器库。现在,我遇到了一个复杂的切片类型和所有权问题。我有一些独立的构建块功能:

pub fn achar(character: char) -> impl Fn(&str) -> Option<char> {
    move |input| match input.chars().next() {
        Some(c) if c == character => Some(c),
        _ => None,
    }
}

pub fn alternatives<'a, T>(
    alts: &'a [impl Fn(&'a str) -> Option<T>],
) -> impl Fn(&'a str) -> Option<T> {
    move |input| {
        for alt in alts.iter() {
            let tried = alt(input);
            if tried.is_none() {
                continue;
            }
            return tried;
        }

        None
    }
}

pub fn one_of<'a>(allowed: &'a str) -> impl Fn(&'a str) -> Option<char> {
    let v = allowed.chars().map(achar).collect::<Vec<_>>();
    alternatives(&v)
}

用法将如下所示:

fn main() {
    println!("{:?}", achar('f')("foo"));
    println!("{:?}", alternatives(vec![achar('f'), achar('b')])("foo"));
    println!("{:?}", one_of("foo")("foo"));
}

就像我收到以下错误:

   = note:   expected type `for<'r> fn(&'r str) -> std::option::Option<char> {any_char}`
           found reference `&impl for<'r> std::ops::Fn<(&'r str,)>`

我想说quote实现了Fn(&str),不是吗?我该如何运作?


一旦解决,下一个问题就在门口:

33 |替代品(&v)| ^^^^^^^^^^^^^^| | || | v是在这里借来的|返回引用当前函数拥有的数据的值

当然,内联不能解决问题。我不知道该如何攻击。

Playground is available here.

types rust closures lifetime ownership
1个回答
0
投票

这里发生了很多事情:

pub fn alternatives<'a, T>(
    alts: &'a [impl Fn(&'a str) -> Option<T>],
) -> impl Fn(&'a str) -> Option<T> {
    move |input| {
        ...
    }
}

以上内容告诉我们alternatives要求切片alts中的所有元素都属于同一类型,并且该类型实现了Fn(&'a str) -> Option<T>。但是,在调用let escaping = alternatives(&vec![any_char, &quote, &backslash]);(甚至简单地为vec![any_char, &quote, &backslash];)中,元素具有不同的类型(一个是any_char类型,下一个quote类型,依此类推)。另一方面,vec![achar('f'), achar('b')]有效,因为所有元素都具有achar类型。

即,即使所有元素都实现Fn(&str)->Option,它们也不是完全相同的类型。

关于下一个错误:

pub fn one_of<'a>(allowed: &'a str) -> impl Fn(&'a str) -> Option<char> {
    let v = allowed.chars().map(achar).collect::<Vec<_>>();
    alternatives(&v)
}

这里,您返回[[借用] alternatives(&v)v。但是v超出了one_of末尾的范围,这意味着alternatives的结果将引用已被破坏的内容,因此生锈不允许这样做。

现在,对于alternatives接受的类型,我们该怎么办?* alternatives可以接受盒装功能。但是,这会增加一些运行时开销,但允许在运行时动态选择的选项。* alternatives可以接受2个功能,并且可以通过宏提供两个以上的功能。这基本上可以在编译时固定替代项的数量,但是没有运行时开销。

one_of中的有效期问题,我们该怎么办?*实际上,这在alternatives中也可能被认为是一个问题,因为alternatives应该可以接受某些函数作为参数并保留它们,以便调用者不必担心生命周期问题。

© www.soinside.com 2019 - 2024. All rights reserved.