Skip to content

Commit

Permalink
Make Combinations lazy
Browse files Browse the repository at this point in the history
To make the `Combinations` adaptor lazy, the operation "prefill the lazy buffer" is now done when handling the first element rather than at definition.

However, the value returned by the `n` method is changed when called on a fresh `it.combinations(k)` since the "prefill" operation was delayed.
I'm perplex on why the method `n` was made public in the first place as the value is subject to change (said in its documentation). But it is public and this change is therefore a breaking one.
  • Loading branch information
Philippe-Cholet authored and jswrenn committed Nov 6, 2023
1 parent 1c8a1e5 commit 63d139d
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 7 deletions.
6 changes: 2 additions & 4 deletions src/combinations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,9 @@ pub fn combinations<I>(iter: I, k: usize) -> Combinations<I>
where
I: Iterator,
{
let mut pool = LazyBuffer::new(iter);
pool.prefill(k);

Combinations {
indices: (0..k).collect(),
pool,
pool: LazyBuffer::new(iter),
first: true,
}
}
Expand Down Expand Up @@ -107,6 +104,7 @@ where
type Item = Vec<I::Item>;
fn next(&mut self) -> Option<Self::Item> {
if self.first {
self.pool.prefill(self.k());
if self.k() > self.n() {
return None;
}
Expand Down
8 changes: 5 additions & 3 deletions tests/test_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1044,7 +1044,7 @@ fn combinations_inexact_size_hints() {
let len = binomial(real_n, k);
assert_eq!(len, it.clone().count());

let mut nb_loaded = numbers.by_ref().take(k).count(); // because of `LazyBuffer::prefill(k)`
let mut nb_loaded = 0;
let sh = numbers.size_hint();
assert_eq!(binomial(sh.0 + nb_loaded, k), it.size_hint().0);
assert_eq!(sh.1.map(|n| binomial(n + nb_loaded, k)), it.size_hint().1);
Expand All @@ -1053,8 +1053,10 @@ fn combinations_inexact_size_hints() {
let elem = it.next();
assert!(elem.is_some());
assert_eq!(len - next_count, it.clone().count());
// It does not load anything more the very first time (it's prefilled).
if next_count > 1 {
if next_count == 1 {
// The very first time, the lazy buffer is prefilled.
nb_loaded = numbers.by_ref().take(k).count();
} else {
// Then it loads one item each time until exhausted.
let nb = numbers.next();
if nb.is_some() {
Expand Down

0 comments on commit 63d139d

Please sign in to comment.