如何通过回调管理生存期



我试图创建一个函数,给定回调,它可以对字符串执行一些操作,并且如果需要进行一些修改,则返回一个新分配的副本。我使用的是std:: borrow::Cow对于这样的事情,但是当我试图使用回调来改变如何对字符串执行操作时,问题就来了。

下面是我要做的一个简化的例子:

use std::borrow::Cow;
pub enum Error {
Test,
}
fn do_lower_case<'a> (s: &'a str) -> Result<Cow<'a, str>, Error>
{   
let s = s.to_lowercase();
Ok(s.into())
}
fn say_hello<'a>(
f: impl Fn(&'a str) -> Result<Cow<'a, str>, Error>,
) -> Result<Cow<'a, str>, Error> 
{   
let s = String::from("Hello");
// Problem: We can not call the callback from here.
// Nevertheless we can call do_lower_case
let s = f(&s)?; // Comment this and uncomment next line works
//let s = do_lower_case(&s)?;
let s = s.into_owned();
Ok(s.into())
}
fn main() {
let res = say_hello(do_lower_case); // Callback is provided here
match res {
Ok(s) => println!("Result: {}", s),
Err(_) => println!("Could not do anything!"),
}
}

这样的事情可以在Rust中完成吗?这是一个生锈游乐场的链接:https://play.rust-lang.org/?version=stable&模式= debug&版= 2021,要点= 8607 d8ac4c34d02236e82e30bcf51e2e

编译器报错,因为s的生存期总是短于'a所能提供的生存期。

要解决这个问题,可以使用更高级别的生命周期。在say_hello函数中指定一个只适用于闭包的生命周期,而不是通用的生命周期。这是通过在implFn之间添加for<'a>来完成的。在此之后,say_hello也不能返回Cow<'a, str>,而需要返回String

fn say_hello(f: impl for<'a> Fn(&'a str) -> Result<Cow<'a, str>, Error>) -> Result<String, Error> {
let s = "Hello";
let s = f(&s)?;
let s = s.into_owned();
Ok(s)
}

或者,下面的代码可能更容易读:

fn say_hello<F>(f: F) -> Result<String, Error>
where
F: for<'a> Fn(&'a str) -> Result<Cow<'a, str>, Error>,
{
let s = "Hello";
let s = f(&s)?;
let s = s.into_owned();
Ok(s)
}

let s = String::from("Hello");改为let s = "Hello";


在这种情况下,您还可以依赖于生存期省略,并可选择使用占位符生存期'_。然后变成:

fn say_hello<F>(f: F) -> Result<String, Error>
where
F: Fn(&str) -> Result<Cow<str>, Error>,
{

fn say_hello<F>(f: F) -> Result<String, Error>
where
F: Fn(&'_ str) -> Result<Cow<'_, str>, Error>,
{

你也可以像原来那样使用impl Fn...内联。

相关内容

  • 没有找到相关文章

最新更新