是 Rust 太难了,还是主流编程本来就这么折磨人? 您所在的位置:网站首页 rust太难了 是 Rust 太难了,还是主流编程本来就这么折磨人?

是 Rust 太难了,还是主流编程本来就这么折磨人?

2024-07-13 08:21| 来源: 网络整理| 查看: 265

where

H: Fn(& 'a Update) -> Fut + Send + Sync + 'a,

Fut: Future + Send + 'a,

{

self.0.push(Box::new(move |upd| Box::pin(handler(upd))));

}

}

fn main {

let mut dp = Dispatcher(vec![]);

dp.push_handler(|upd| async move {

println!("{:?}", upd);

});

}

在这里,我们使用由 HRTB 生命周期 for src/main.rs:12:21

|

12 | fn push_handler限定的BoxFuture:

use futures::future::BoxFuture;

#[derive(Debug)]

struct Update;

typeHandler = Box BoxFuture< 'a, > + Send + Sync>;

struct Dispatcher(Vec);

impl Dispatcher {

fn push_handler(&mut self, handler: H)

where

H: for BoxFuture Self::Out;

}

impl PushHandler forDispatcherEnd {

typeOut = Dispatcher;

fn push_handler(self, handler: NewH) -> Self::Out {

Dispatcher {

handler,

tail: DispatcherEnd,

}

}

}

impl PushHandler forDispatcher

where

Tail: PushHandler,

{

typeOut = Dispatcher;

fn push_handler(self, handler: NewH) -> Self::Out {

Dispatcher {

handler: self.handler,

tail: self.tail.push_handler(handler),

}

}

}

有些朋友可能不太熟悉所谓类型级归纳,其实这就是一种常规递归,只是适用对象是类型(trait)、而非值:

这里的 base case 就是 impl PushHandler for DispatcherEnd。我们构建一个 dispatcher,其中只包含一个处理程序。 而 step case 则是 impl PushHandler for Dispatcher。这里我们只将归纳传播至 self.tail。

我们再以同样的方式实现 execute:

trait Execute< 'a> {

#[must_use]

fn execute(&' a self, upd: & 'a Update) -> BoxFuture Execute {

Box::pin(async {})

}

}

impl for Dispatcher

where

H: Fn(&' a Update) -> Fut + Send + Sync + 'a,

Fut: Future + Send + ' a,

Tail: Execute< 'a> + Send + Sync + 'a,

{

fn execute(& 'a self, upd: &'a Update) -> BoxFuture< 'a, > {

Box::pin(async move {

(self.handler)(upd).await;

self.tail.execute(upd).await;

})

}

}

但这还不够。因为我们 Execute,

{

dp.execute(&upd).await;

}

好了,现在我们要来测试这种神奇的解决方案:

#[tokio::main]

async fn main{

letdp = DispatcherEnd;

letdp = dp.push_handler(|upd| async move {

println!( "{:?}", upd);

});

execute(dp, Update).await;

}

可惜还是行不通:

error: implementation of `Execute` is not general enough

--> src/main.rs:83:5

|

83 | execute(dp, Update).await;

| ^^^^^^^ implementation of `Execute` is not general enough

|

= note: `Dispatcher` must implement `Execute< '0>`, for any lifetime `'0`...

= note: ...but it actually implements `Execute< '1>`, for some specific lifetime `'1`

到这里,很多朋友应该体会到借用检查器的可惜之处了吧?而且无论怎么调整,以上代码都没办法正常编译。原因如下:传递给 dp.push_handler 的闭包接收到一条具体生命周期为'1 的 upd,但因为 where 子句中引入了 HRTB 边界,所以 execute 要求 Dp 只在生命周期 '0 上实现 Execute fn(&'r Update):

error[E0308]: mismatched types

--> src/main.rs:9:9

|

9 | let= dbg_update_fn;

| ^^ ------------- this expression has type` for< 'r> fn(&'r Update) {dbg_update_fn}`

| |

| expected fn item, found ``

|

= note: expected fn item ` for< 'r> fn(&'r Update) {dbg_update_fn}`

found unit type``

话虽如此,但这样一个包含异构列表的答案也不符合我们的预期:它太过混乱、僵化、复杂,而且也装不进闭包。另外,这里不建议在 Rust 中使用复杂的类型机制。如果大家在处理 dispatcher 类型时突然遇到类型检查失败,那麻烦可就大了。想象一下,我们正在维护一套用 Rust 编写的生产系统,而且需要尽快修复一些关键 bug。而在完成了代码库的必要更改之后,却看到了以下编译输出:

error[E0308]: mismatched types

--> src/main.rs:123:9

|

123 | let= dp;

| ^^ -- this expression has type`Dispatcher< for< '_> fn(&Update) -> impl futures::Future {dbg_update0}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update2}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update4}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update6}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update8}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update0}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update2}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update4}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update6}, Dispatcher fn(&Update) -> impl futures::Future {dbg_update8}, Dispatcher



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有