3 回答
TA贡献1796条经验 获得超10个赞
Either
使用futures::future::Either没有额外的堆分配:
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)))
}
}
但是,这需要固定的堆栈分配。如果A占用1个字节并在99%的时间内发生,但B占用512个字节,则您Either将始终占用512个字节(加上一些字节)。这并不总是胜利。
装箱特征对象
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)))
}
}
正如Matthieu M.指出的那样,可以将两种解决方案结合起来:
我要指出,有相当大的情况下,中间地带的解决方案B:Either(A, Box<B>)。这样,您仅需在少数情况下为堆分配付费B
请注意,Either如果您有两个以上的条件(Either<A, Either<B, C>>; Either<Either<A, B>, Either<C, D>>等),也可以堆叠s :
fn f(v: i32) -> impl Future<Item = i32, Error = ()> {
use std::cmp::Ordering;
match v.cmp(&0) {
Ordering::Less => Either::A(future::ok(2).map(|x| -x)),
Ordering::Equal => Either::B(Either::A(future::ok(0))),
Ordering::Greater => Either::B(Either::B(future::ok(-2).map(|x| x * x))),
}
}
TA贡献1786条经验 获得超12个赞
r我试图说Either<Either<A, B>, C>
可以写成Either<Either<A, B>, Either<C, Empty<_, _>>>
。但是现在我不确定是否会更好。两种类型都同样嵌套,但这似乎不是优势。我想我太复杂了
TA贡献1869条经验 获得超4个赞
我给出了3个(奇数)和4个(偶数)条件的示例:如果您有2个以上的条件(Either<A, Either<B, C>>
; Either<Either<A, B>, Either<C, D>>
等)。我不明白你为什么用Empty
。
添加回答
举报