MCPcopy Index your code
hub / github.com/danielhenrymantilla/lending-iterator.rs

github.com/danielhenrymantilla/lending-iterator.rs @v0.1.7

Chat with this repo
repository ↗ · DeepWiki ↗ · release v0.1.7 ↗ · + Follow
61 symbols 81 edges 26 files 25 documented · 41% updated 2y agov0.1.7 · 2023-04-04★ 887 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

::lending-iterator

Repository Latest version Documentation MSRV unsafe forbidden License CI

Fully generic LendingIterators in stable Rust.

  • this pattern used to be called StreamingIterator, but since Streams entered the picture (as the async/.await version of Iterators, that is, AsyncIterators), it has been deemed more suitable to go for the lending naming convention.

    • (this could be even more relevant since you can have a LendingIterator lending impl Futures, which would effectively make it another flavor of AsyncIterator, but not quite the Stream variant).
  • For context, this crate is a generalization of other crates such as:

    which hard-code their lending Item type to &_ and Result<&_, _> respectively.

    This crate does not hardcode such dependent types, and thus encompasses both of those traits, and infinitely more!

  • Mainly, it allows lending &mut _ Items, which means it can handle the infamously challenging [windows_mut()] pattern!

Examples

Click to hide

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],
);

Rolling your own version of it using the handy from_fn constructor

  • (Or even the FromFn flavor of it to enjoy "named arguments")
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],
);
  • where that HKT!(\&mut [u16; 3]) is a higher-kinded type parameter that has to be turbofished to let the generic context properly figure out the return type of the next closure.

    Indeed, if we were to let type inference, alone, figure it out, it wouldn't be able to know which lifetimes would be fixed/tied to call-site captures, and which would be tied to the "lending-ness" of the iterator (higher-order return type). See ::higher-order-closure for more info about this.

LendingIterator adapters

See [lending_iterator::adapters].


Bonus: Higher-Kinded Types (HKT)

See higher_kinded_types for a presentation about them.

Real-life usage: .sort_by_key() that is fully generic over the key lending mode

As noted in this 6-year-old issue:

Such an API can easily be provided using the HKT API of this crate:

Click to show

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);
}

Extension points exported contracts — how you extend this code

WithLifetime (Interface)
[`HKT`][trait@HKT]'s internals. Mainly expected to be used **to query** the type off an `impl HKT` obtained by [Apply]i [2 …
src/higher_kinded_types.rs
FnMut (Interface)
Helper trait to allow expressing `F : FnMut(Arg) -> _` bounds (existential return type). [1 implementers]
src/utils/mod.rs
LendingIteratorDyn (Interface)
`dyn`-friendly (`dyn`-safe) version of [`LendingIterator`]. It is automagically implemented for all types implementing [1 …
src/lending_iterator/dyn/_mod.rs
HKT (Interface)
A trait to help express [Higher Kinded Types][self]. Use `: HKT` as a trait bound when intending to received parameters [1 …
src/higher_kinded_types.rs
DynCoerce (Interface)
Let's not overwhelm users of the crate with info.
src/lending_iterator/dyn/_mod.rs

Core symbols most depended-on inside this repo

ensure_skipped
called by 2
src/lending_iterator/adapters/skip.rs
next
called by 2
src/lending_iterator/adapters/map.rs
hkt_lifetime
called by 2
src/proc_macros/mod.rs
next
called by 1
src/lending_iterator/impls.rs
from_iter
called by 1
src/lending_iterator/constructors/from_iter.rs
windows_mut
called by 1
src/lending_iterator/constructors/windows_mut_.rs
nth
called by 1
src/lending_iterator/constructors/windows_mut_.rs
nth
called by 1
src/lending_iterator/adapters/skip.rs

Shape

Method 25
Class 16
Function 14
Interface 5
Enum 1

Languages

Rust100%

Modules by API surface

src/proc_macros/mod.rs8 symbols
examples/higher_kinded_types.rs5 symbols
src/lending_iterator/constructors/windows_mut_.rs4 symbols
src/lending_iterator/adapters/skip.rs4 symbols
src/lending_iterator/dyn/_mod.rs3 symbols
src/lending_iterator/constructors/repeat_mut.rs3 symbols
src/lending_iterator/constructors/from_stream.rs3 symbols
src/lending_iterator/constructors/from_iter.rs3 symbols
src/lending_iterator/constructors/from_fn.rs3 symbols
src/lending_iterator/adapters/take.rs3 symbols
src/lending_iterator/adapters/map.rs3 symbols
src/lending_iterator/adapters/filter_map.rs3 symbols

For agents

$ claude mcp add lending-iterator.rs \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page