How do I conditionally return different types of futures?

◇◆丶佛笑我妖孽 提交于 2019-11-26 16:43:36

Either

Using futures::future::Either has no additional heap allocation:

extern crate futures; // 0.1.23

use futures::{
    future::{self, Either},
    Future,
};

fn f() -> impl Future<Item = usize, Error = ()> {
    if 1 > 0 {
        Either::A(future::ok(2).map(|x| x))
    } else {
        Either::B(future::ok(10).and_then(|x| future::ok(x + 2)))
    }
}

However, this requires a fixed stack allocation. If A takes 1 byte and happens 99% of the time, but B takes up 512 bytes, your Either will always take up 512 bytes (plus some). This isn't always a win.

Boxed trait objects

extern crate futures; // 0.1.23

use futures::{future, Future};

fn f() -> Box<Future<Item = usize, Error = ()>> {
    if 1 > 0 {
        Box::new(future::ok(2).map(|x| x))
    } else {
        Box::new(future::ok(10).and_then(|x| future::ok(x + 2)))
    }
}

As Matthieu M. points out, the two solutions can be combined:

I would note that there is a middle ground solution for the case of a large B: Either(A, Box<B>). This way, you only pay for the heap allocation on the rare case where it's a B

Note that you can also stack Eithers if you have more than 2 conditions (Either<A, Either<B, C>>; Either<Either<A, B>, Either<C, D>>, etc.):

See also:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!