Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Types 锈函数签名与寿命_Types_Rust_Closures_Lifetime_Ownership - Fatal编程技术网

Types 锈函数签名与寿命

Types 锈函数签名与寿命,types,rust,closures,lifetime,ownership,Types,Rust,Closures,Lifetime,Ownership,为了学习Rust,我正在编写一个解析器组合器库。现在我遇到了一个跨越复杂切片类型和所有权的问题。我有一些构建块函数,我希望能够单独使用: pub-fn-achar(字符:char)->impl-fn(&str)->选项{ 移动|输入|匹配input.chars().next(){ 如果c==字符=>Some(c),则为Some(c), _=>没有, } } pub fn备选方案{ 移动|输入|{ 对于alts.iter()中的alt{ let=alt(输入); 如果尝试过。是否没有(){ 继续;

为了学习Rust,我正在编写一个解析器组合器库。现在我遇到了一个跨越复杂切片类型和所有权的问题。我有一些构建块函数,我希望能够单独使用:

pub-fn-achar(字符:char)->impl-fn(&str)->选项{
移动|输入|匹配input.chars().next(){
如果c==字符=>Some(c),则为Some(c),
_=>没有,
}
}
pub fn备选方案{
移动|输入|{
对于alts.iter()中的alt{
let=alt(输入);
如果尝试过。是否没有(){
继续;
}
返回尝试;
}
没有一个
}
}
pub fn impl fn(&'a str)->选项之一{
让v=allowed.chars().map(achar.collect::();
备选方案(&v)
}
使用情况如下所示:

fn main(){
println!(“{:?}”,achar('f')('foo”);
println!(“{:?}”),备选方案(vec![achar('f')、achar('b'))('foo”);
println!(“{:?}”,一个“foo”)(“foo”);
}
这样,我得到了以下错误:

=注意:std::option::option{any_char}的类型应为``
找到的引用“%impl”`
我想说
quote
实现了
Fn(&str)
,不是吗?我怎样才能让它工作


一旦这些问题得到解决,下一个问题就在门口:

33 | alternatives(&v) | ^^^^^^^^^^^^^--^ | | | | | `v` is borrowed here | returns a value referencing data owned by the current function 33 |备选方案(&v) | ^^^^^^^^^^^^^--^ | | | ||'v'在这里借用 |返回引用当前函数拥有的数据的值 当然,内联并不能解决问题。我不知道怎么去攻击它


这里发生了很多事情:

pub fn alternatives<'a, T>(
    alts: &'a [impl Fn(&'a str) -> Option<T>],
) -> impl Fn(&'a str) -> Option<T> {
    move |input| {
        ...
    }
}
在这里,您返回借用
v
alternations(&v)
。但是
v
one_of
的末尾超出了范围,这意味着
备选方案的结果将指向已销毁的东西,因此生锈不允许这样做

现在,对于
备选方案所接受的类型,我们能做些什么

  • 备选方案
    可以接受装箱函数。然而,这会产生一些运行时开销,但会允许在运行时动态地选择备选方案的数量
  • 备选方案
    可以接受函数指针。然而,这将禁止(环境捕获)关闭
  • 备选方案
    可以接受两个函数,并且可以通过宏提供两个以上的函数。这基本上可以在编译时固定备选方案的数量,但没有运行时开销
对于
one\u of
中的生存期问题,我们可以做些什么

  • 这实际上也可能被认为是
    备选方案
    中的一个问题,因为
    备选方案
    可能会接受一些函数作为参数,并保留它们,以便调用者不必担心生存期问题

您帖子中的代码不会导致与操场上的代码相同的错误。谢谢。在写这篇文章的时候,我还在努力让它发挥作用。我一定是把版本弄混了。我可以接受
备选方案
的所有权并改变它。但是我很惊讶,你不能传递一个行为相同的函数数组(即相同的签名和全部)。切片是否比
Vec
更有效?只有相同签名的函数的问题在于它们可能是闭包,即某些函数可能“捕获”变量(例如您捕获一个字符)。如果您想拥有所有权,则
Vec
可能是更好的选择(由于切片不打开其数据,而
Vec
打开其数据)。
pub fn one_of<'a>(allowed: &'a str) -> impl Fn(&'a str) -> Option<char> {
    let v = allowed.chars().map(achar).collect::<Vec<_>>();
    alternatives(&v)
}