::lending-iterator
Fully generic LendingIterator
s in stable Rust.
this pattern used to be called StreamingIterator
, but since Stream
s entered
the picture (as the async/.await
version of Iterator
s, that is,
AsyncIterator
s), it has been deemed more suitable to go for the lending
naming convention.
LendingIterator
lending impl Future
s, 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 _
Item
s, which means it can handle the
infamously challenging [windows_mut()
] pattern!
Click to hide
windows_mut()
!```rust 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.windowsmut::<3>(); // windowsmut::<_, 3>(&mut array);
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
constructorFromFn
flavor of it to enjoy "named arguments")```rust 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;
lendingiterator::FromFn::&mut [u8] -> &mut [u8; 3]
.unwrap()
;
start += 1;
Some(toyield)
},
phantom: <_>::default(),
}
};
while let Some(&mut [a, b, ref mut next]) = iter.next() {
*next = a + b;
}
asserteq!(
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```rust 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 = {
::lendingiterator::repeatmut((0, &mut array))
.filtermaptomut(|[], (start, array)| -> Option<&mut [u16]> {
let toyield =
array
.getmut(*start..)?
.getmut(..3)?
;
*start += 1;
Some(toyield)
})
.maptomut::<[u16; 3], _>(|[], slice| slice.tryinto().unwrap())
};
while let Some(&mut [a, b, ref mut next]) = iter.next() {
*next = a + b;
}
// drop(iter);
assert_eq!(
array,
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377],
);
```
&mut
for {and_then, map}_to_mut()
) are required to take an extra []
"dummy" parameter for the closure input. This is due to a technical
limitation of the language, and having to add [],
was the least
cumbersome way that I could find to work around it 😔