1个不稳定版本

0.1.0 2021年12月20日

#7 in #suspend

Download history 15/week @ 2024-03-30 1/week @ 2024-04-06 47/week @ 2024-06-08 4/week @ 2024-06-15

每月51次下载
suspend_fn中使用

Apache-2.0

16KB
456

suspend fn

免责声明:这个项目主要是作为下面提议的实验概念。我没有测试这个宏是否有性能成本。

这个crate提供了一个过程宏,用于移除对await关键字的需求。例如

#[suspend_fn]
fn visit_rustlang() -> Result<(), reqwest::Error> {
    let response = reqwest::get("https://rust-lang.net.cn")?;
    let text = response.text()?;
    println!("{}", text);
    text.len(); // sync functions work just fine!
    Ok(())
}

上面的代码在功能上是等价的

async fn visit_rustlang() -> Result<(), reqwest::Error> {
    let response = reqwest::get("https://rust-lang.net.cn").await?;
    let text = response.text().await?;
    println!("{}", text);
    text.len(); 
    Ok(())
}

suspend块

您还可以像对asyncasync move块一样使用suspend!suspend_move!宏。注意,这可能会触发样式警告,因此我建议在crate根目录中放置#![allow(unused_parens)]

#![allow(unused_parens)]
suspend! { 
    let response = reqwest::get("https://rust-lang.net.cn")?;
    let text = response.text()?;
    println!("{}", text);
    text.len(); 
}

限制

目前,这个宏在其它宏内部不起作用。例如

println!("{}", async_fn());

上面的代码将引发以下错误信息

| println!("{}", async_fn()); 
|                ^^^^^^^^^^  `impl Future` cannot be formatted with the default formatter

对于这种情况,您可以在宏中自己简单地使用.await

动机

在一篇关于异步取消问题的博客文章中,有人认为异步析构函数会导致语言设计方面的不一致性。这是因为编译器会为异步析构函数引入.await调用,使得一些.await调用是隐式的,而另一些是显式的。

作为解决这种冲突的一种方式,有人提出了完全移除.await语法的建议。虽然我认为这在人机工程学方面会很棒,但我不想看到如此大的破坏性变化。作为替代方案,我建议添加一个与async类似的新关键字,暂时让我们使用Kotlin的suspend

然后我们可以有

suspend fn function() {
    /* 
        implicit await with implicit calls to async destructors
    */
}
async fn function() {
    /* 
        explicit await with explicit calls to async destructors
    */
}

async {
    /* 
        explicit await with explicit calls to async destructors
    */
}

suspend {
    /* 
        implicit await with implicit calls to async destructors
    */
}

依赖项

~1.5MB
~35K SLoC