#hkt #streaming #generics #gat #async-await #windows-mut #streaming-iterator

不使用 std lending-iterator

稳定 Rust 中的完全通用借款迭代器:windows_mut!

16 个版本

0.1.7 2023 年 4 月 4 日
0.1.7-rc12023 年 4 月 2 日
0.1.6 2022 年 8 月 8 日
0.1.5 2022 年 7 月 22 日
0.0.0 2022 年 5 月 26 日

185 in Rust 模式

Download history 12807/week @ 2024-04-20 17015/week @ 2024-04-27 12379/week @ 2024-05-04 17211/week @ 2024-05-11 16822/week @ 2024-05-18 17214/week @ 2024-05-25 18766/week @ 2024-06-01 12674/week @ 2024-06-08 15991/week @ 2024-06-15 19929/week @ 2024-06-22 16098/week @ 2024-06-29 9134/week @ 2024-07-06 8753/week @ 2024-07-13 8990/week @ 2024-07-20 7839/week @ 2024-07-27 6618/week @ 2024-08-03

33,490 个月下载量
用于 7 个crate(5 个直接使用)

Zlib OR MIT OR Apache-2.0

88KB
1.5K SLoC

::借款-迭代器

Repository Latest version Documentation MSRV unsafe forbidden License CI

稳定 Rust 中的完全泛型 LendingIterator

  • 这个模式以前被称为 StreamingIterator,但由于 Stream 出现了(作为 async/.await 版本的 Iterator,即 AsyncIterator),因此更倾向于采用 借款 命名约定。

    • (这甚至可能更为相关,因为你可以有一个借款 LendingIterator 借款 impl Future,这将实际上使其成为另一种 AsyncIterator 的风味,但不是 Stream 变体)。
  • 为了说明背景,这个crate是其他crate(如)的泛化

    它们将借款 Item 类型分别硬编码为 &_Result<&_, _>

    这个crate没有硬编码这样的依赖类型,因此包含了两个这些特性和无限更多!

  • 主要,它允许借款 &mut _ Item,这意味着它可以处理臭名昭著的 windows_mut() 模式!

示例

点击隐藏

windows_mut()!

use ::lending_iterator::prelude::*;

let mut array = [0; 15];
array[1] = 1;
// Cumulative sums are trivial with a `mut` sliding window,
// so let's showcase that by generating a Fibonacci sequence.
let mut iter = array.windows_mut::<3>();
while let Some(&mut [a, b, ref mut next]) = iter.next() {
    *next = a + b;
}
assert_eq!(
    array,
    [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377],
);

使用方便的 from_fn 构造函数自己实现一个版本

  • (或者使用 FromFn 风格来享受“命名参数”)
use ::lending_iterator::prelude::*;

let mut array = [0; 15];
array[1] = 1;
// Let's hand-roll our iterator lending `&mut` sliding windows:
let mut iter = {
    let mut start = 0;
    lending_iterator::FromFn::<HKT!(&mut [u16; 3]), _, _> {
        state: &mut array,
        next: move |array| {
            let to_yield =
                array
                    .get_mut(start..)?
                    .get_mut(..3)?
                    .try_into() // `&mut [u8] -> &mut [u8; 3]`
                    .unwrap()
            ;
            start += 1;
            Some(to_yield)
        },
        _phantom: <_>::default(),
    }
};
while let Some(&mut [a, b, ref mut next]) = iter.next() {
    *next = a + b;
}
assert_eq!(
    array,
    [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377],
);
  • 这里的 HKT!(&mut [u16; 3]) 是一个 高阶类型参数,它必须通过 turbofishing 来确保泛型上下文能够正确地推断出 next 封闭的返回类型。

    实际上,如果我们仅让类型推断来完成这项工作,它将无法知道哪些生命周期将固定/绑定到调用站点捕获,以及哪些将绑定到迭代器的“lending”(高阶返回类型)特性。有关更多信息,请参阅 ::higher-order-closure

LendingIterator 适配器

请参阅 lending_iterator::adapters


附加:高阶类型(HKT)

有关它们的信息,请参阅 higher_kinded_types

实际使用:对键 lending 模式完全泛型的 .sort_by_key()

如在此 6 年前的 issue 中所述

使用此 crate 的 HKT API 可以轻松地提供此类 API

点击显示
use ::lending_iterator::higher_kinded_types::{*, Apply as A};

fn slice_sort_by_key<Key, Item, KeyGetter> (
    slice: &'_ mut [Item],
    mut get_key: KeyGetter,
)
where
    Key : HKT, // "Key : <'_>"
    KeyGetter : for<'item> FnMut(&'item Item) -> A!(Key<'item>),
    for<'item>
        A!(Key<'item>) : Ord
    ,
{
    slice.sort_by(|a, b| Ord::cmp(
        &get_key(a),
        &get_key(b),
    ))
}

// ---- Demo ----

struct Client { key: String, version: u8 }

fn main ()
{
    let clients: &mut [Client] = &mut [];

    // Error: cannot infer an appropriate lifetime for autoref due to conflicting requirements
    // clients.sort_by_key(|c| &c.key);

    // OK
    slice_sort_by_key::<HKT!(&str), _, _>(clients, |c| &c.key);

    // Important: owned case works too!
    slice_sort_by_key::<HKT!(u8), _, _>(clients, |c| c.version);
}

依赖项

~1.5MB
~38K SLoC