如何为闭包参数声明生命周期? [英] How to declare a lifetime for a closure argument?

查看:19
本文介绍了如何为闭包参数声明生命周期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 Rust 中为闭包声明一个生命周期,但我找不到添加生命周期声明的方法.

使用 std::str::SplitWhitespace;酒吧结构解析器错误{发布消息:字符串,}fn missing_token(line_no: usize) ->解析器错误{解析器错误{消息:格式!(第 {} 行缺少令牌",line_no),}}fn process_string(line: &str, line_number: usize) ->结果<(),解析器错误>{让 mut 标记 = line.split_whitespace();匹配 try!(tokens.next().ok_or(missing_token(line_number))) {嗨" =>println!("你好"),_ =>println!("别的东西"),}//下面的代码给出了无法推断合适的生命周期.....//让 nt = |t: &mut SplitWhitespace|t.next().ok_or(missing_token(line_number));//匹配 try!(nt(&mut tokens)) {//那里" =>println!("那里"),//_ =>println!("_"),//}//我应该在哪里声明生命周期 'a?//let nt = |t: &'a mut SplitWhitespace|t.next().ok_or(missing_token(line_number));//匹配 try!(nt(&mut tokens)) {//那里" =>println!("那里"),//_ =>println!("_"),//}返回 Ok(());}fn 主(){process_string("你好", 5).ok().expect("Error!!!");process_string("", 5).ok().expect("Error!!! 2");}

playground 上的完整示例代码.

error[E0495]:由于需求冲突,无法为生命周期参数a"推断合适的生命周期-->src/main.rs:22:42|22 |让 nt = |t: &mut SplitWhitespace|t.next().ok_or(missing_token(line_number));|^^^^|注意:首先,生命周期不能超过 22:14 在主体上定义的匿名生命周期 #2 ...-->src/main.rs:22:14|22 |让 nt = |t: &mut SplitWhitespace|t.next().ok_or(missing_token(line_number));|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^= 注意:...以便类型兼容:预期 std::iter::Iterator找到 std::iter::Iterator注意:但是,生命周期必须对 23:16 的调用有效...-->src/main.rs:23:16|23 |匹配 try!(nt(&mut 标记)) {|^^^^^^^^^^^^^^^^注意:...所以类型`std::result::Result<&str, ParserError>` 的表达式在表达式期间是有效的-->src/main.rs:23:16|23 |匹配 try!(nt(&mut tokens)) {|^^^^^^^^^^^^^^^^

如何为这个闭包声明生命周期'a?

解决方案

&mut SplitWhitespace 实际上是一个 &'b mut SplitWhitespace<'a>.这里的相关生命周期是 'a,因为它指定了 next 返回的字符串切片的有效时间.由于您在 line 参数上应用了 split_whitespace 函数,您需要将 'a 设置为与 line 相同的生命周期代码>参数有.

因此,作为第一步,您向 line 添加生命周期:

fn process_string<'a>(line: &'a str, line_number: usize) ->结果<(),解析器错误>{

然后将生命周期添加到闭包中的类型:

let nt = |t: &mut SplitWhitespace<'a>|t.next().ok_or(missing_token(line_number));

请注意,虽然这可以回答您的问题,但问题的正确解决方案是@AB 的解决方案.>

I would like to declare a lifetime for a closure in Rust, but I can't find a way to add a lifetime declaration.

use std::str::SplitWhitespace;

pub struct ParserError {
    pub message: String,
}

fn missing_token(line_no: usize) -> ParserError {
    ParserError {
        message: format!("Missing token on line {}", line_no),
    }
}

fn process_string(line: &str, line_number: usize) -> Result<(), ParserError> {
    let mut tokens = line.split_whitespace();

    match try!(tokens.next().ok_or(missing_token(line_number))) {
        "hi" => println!("hi"),
        _ => println!("Something else"),
    }

    // The following code gives "cannot infer appropriate lifetime.....
    // let nt = |t: &mut SplitWhitespace| t.next().ok_or(missing_token(line_number));
    // match try!(nt(&mut tokens)) {
    //     "there" => println!("there"),
    //     _ => println!("_"),
    // }

    // Where should I declare the lifetime 'a?
    // let nt = |t: &'a mut SplitWhitespace| t.next().ok_or(missing_token(line_number));
    // match try!(nt(&mut tokens)) {
    //     "there" => println!("there"),
    //     _ => println!("_"),
    // }

    return Ok(());
}

fn main() {
    process_string("Hi there", 5).ok().expect("Error!!!");
    process_string("", 5).ok().expect("Error!!! 2");
}

Complete sample code on the playground.

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
  --> src/main.rs:22:42
   |
22 |     let nt = |t: &mut SplitWhitespace| t.next().ok_or(missing_token(line_number));
   |                                          ^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 22:14...
  --> src/main.rs:22:14
   |
22 |     let nt = |t: &mut SplitWhitespace| t.next().ok_or(missing_token(line_number));
   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: ...so that the types are compatible:
           expected std::iter::Iterator
              found std::iter::Iterator
note: but, the lifetime must be valid for the call at 23:16...
  --> src/main.rs:23:16
   |
23 |     match try!(nt(&mut tokens)) {
   |                ^^^^^^^^^^^^^^^
note: ...so type `std::result::Result<&str, ParserError>` of expression is valid during the expression
  --> src/main.rs:23:16
   |
23 |     match try!(nt(&mut tokens)) {
   |                ^^^^^^^^^^^^^^^

How can I declare the lifetime 'a for this closure?

解决方案

The &mut SplitWhitespace is actually a &'b mut SplitWhitespace<'a>. The relevant lifetime here is the 'a, as it specifies how long the string slices that next returns live. Since you applied the split_whitespace function on your line argument, you need to set 'a to the same lifetime that the line argument has.

So as a first step you add a lifetime to line:

fn process_string<'a>(line: &'a str, line_number: usize) -> Result<(), ParserError> {

and then you add the lifetime to the type in your closure:

let nt = |t: &mut SplitWhitespace<'a>| t.next().ok_or(missing_token(line_number));

Note that while this answers your question, the correct solution to your Problem is @A.B.'s solution.

这篇关于如何为闭包参数声明生命周期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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