函数参数

时间:2018-04-18 07:58:15

标签: rust lifetime

我正在尝试编写这段小代码,但我无法使用它。我对Rust的经验很少,尤其是有生命周期。

我在一个较小的脚本中重现了错误:

fn main() {
    let app = App {
        name: &String::from("Davide"),
    };
    app.run();
}

struct App<'a> {
    name: &'a String,
}

impl<'a> App<'a> {
    fn run(self) {
        let result = App::validator_1(App::validator_2(App::box_command()))(self);
        println!("{}", result)
    }

    fn validator_1(next: Box<Fn(App) -> String>) -> Box<Fn(App) -> String> {
        Box::new(move |app: App| -> String { next(app) })
    }

    fn validator_2(next: Box<Fn(App) -> String>) -> Box<Fn(App) -> String> {
        Box::new(move |app: App| -> String { next(app) })
    }

    fn box_command() -> Box<Fn(App) -> String> {
        Box::new(App::command)
    }

    fn command(self) -> String {
        format!("Hello {}!", self.name)
    }
}

当我编译它时,我收到此错误:

error[E0631]: type mismatch in function arguments
  --> src/main.rs:27:9
   |
27 |         Box::new(App::command)
   |         ^^^^^^^^^^^^^^^^^^^^^^ expected signature of `for<'r> fn(App<'r>) -> _`
...
30 |     fn command(self) -> String {
   |     -------------------------- found signature of `fn(App<'_>) -> _`
   |
   = note: required for the cast to the object type `for<'r> std::ops::Fn(App<'r>) -> std::string::String`

error[E0271]: type mismatch resolving `for<'r> <fn(App<'_>) -> std::string::String {App<'_>::command} as std::ops::FnOnce<(App<'r>,)>>::Output == std::string::String`
  --> src/main.rs:27:9
   |
27 |         Box::new(App::command)
   |         ^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime
   |
   = note: required for the cast to the object type `for<'r> std::ops::Fn(App<'r>) -> std::string::String`

我了解问题与name App的生命周期有关,但我不知道如何修复它。

1 个答案:

答案 0 :(得分:3)

command函数的签名与box_command预期返回的签名不匹配。

box_command应该包含以下内容:

fn box_command() -> Box<Fn(App) -> String> {
    Box::new(move |app: App| -> String { app.command() })
}

编译器期望调用返回String。上述更改将允许以下语句中的self作为app参数传递。因此app.command()满足整个流程并从调用链返回String

let result = App::validator_1(App::validator_2(App::box_command()))(self);