gpt4 book ai didi

rust - 为什么 Stream 为扩展特征而不是特征本身提供方便的方法?

转载 作者:行者123 更新时间:2023-12-03 13:32:25 28 4
gpt4 key购买 nike

考虑 Iterator 来自标准库的特性:

pub trait Iterator {
type Item;

// required
pub fn next(&mut self) -> Option<Self::Item>;

// potentially advantageous to override
pub fn size_hint(&self) -> (usize, Option<usize>) { ... }
pub fn count(self) -> usize { ... }
pub fn last(self) -> Option<Self::Item> { ... }
pub fn advance_by(&mut self, n: usize) -> Result<(), usize> { ... }
pub fn nth(&mut self, n: usize) -> Option<Self::Item> { ... }

// convenience
pub fn step_by(self, step: usize) -> StepBy<Self> { ... }
pub fn chain<U>(self, other: U) -> Chain<Self, U::IntoIter> { ... }
pub fn zip<U>(self, other: U) -> Zip<Self, U>::IntoIter> { ... }
pub fn map<B, F>(self, f: F) -> Map<Self, F> { ... }
pub fn for_each<F>(self, f: F) { ... }
...
}
并考虑 Stream StreamExt 来自 futures 的特征箱:
pub trait Stream {
type Item;

// required
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>;

// potentially advantageous to override
fn size_hint(&self) -> (usize, Option<usize>) { ... }
}

pub trait StreamExt: Stream {
// convenience
pub fn next(&mut self) -> Next<'_, Self> { ... }
pub fn into_future(self) -> StreamFuture<Self> { ... }
pub fn map<T, F>(self, f: F) -> Map<Self, F> { ... }
pub fn enumerate(self) -> Enumerate<Self> { ... }
pub fn filter<Fut, F>(self, f: F) -> Filter<Self, Fut, F> { ... }
...
}

impl<T> StreamExt for T where T: Stream { ... }
鉴于 Stream,它们有很多相似之处。本质上是一个 async Iterator 的版本.但是,我想提请注意它们的差异。
为什么它们的结构不同?
我看到的拆分特征的唯一好处是 StreamExt方法不能被覆盖。这样它们就可以保证按预期运行,而 Iterator 的便利方法可以被覆盖以表现不一致。但是,我无法想象这是一个需要考虑防范的常见问题。而这种差异是以可访问性和可发现性为代价的,需要用户导入 StreamExt使用它们并首先知道它们的存在。
鉴于 Stream之后 Iterator很明显, split 是一个深思熟虑的决定,但动机是什么?当然,它比我想象的要多。 Iterator 有什么不好的地方吗?设计?
当由另一个 crate 提供时,当然需要扩展特征,但这个问题与此无关。

最佳答案

拆分的最大优点是实现便捷方法的 trait 可以在与核心方法不同的 crate 中实现。这对于 Future vs FutureExt trait 很重要,因为它允许 Future trait 的核心方法移动到 std 中,而无需标准化 FutureExt 便利方法。
这有两个优点:首先,Future 可以进入核心,因为核心方法不依赖于分配器,而一些方便的方法可能会。其次,它减少了标准化的表面积,以最小化标准化一个高优先级的特性的成本,以便标准化 async/await。相反,现在可以在 FutureExt 中继续在 futures crate 中迭代便利方法。
那么为什么 Future vs FutureExt 与 Stream vs StreamExt 相关?首先,Stream 是 Future 的扩展,因此有一个论据是遵循相同的模式。但更重要的是,人们期望在某个时候 Stream 将被标准化,可能会使用一些语法糖来处理 async/await。通过现在拆分,将核心功能迁移到 std/core 的成本被最小化。长期计划似乎是核心功能将从 future 转移到标准/核心,而 future 将成为扩展功能的更快开发/风险更低的位置。
作为历史记录,0.1.x 的 future 使用了 Future 和 Stream 的便捷方法的迭代器样式。这在 0.2.x 中作为导致 async/await 的实验/迭代的一部分进行了更改。

关于rust - 为什么 Stream 为扩展特征而不是特征本身提供方便的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66754268/

28 4 0