Repository: rust-itertools/itertools (language: rust)

Issue:
Combination on zero-sized array
Combination(0) seems to return an empty array.
However, the result differs when the original list is empty or not.

I think it would be better to produce [] instead of None.

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=dad32c5aeae27dcd9b14ce8475b5fa79

```{.rs}
use itertools::*; // 0.8.0
fn main() {
    let a: Vec<usize> = vec![1usize];
    let b: Vec<usize> = vec![];
    println!("{:?}", a.iter().combinations(0).next()); // Some([])
    println!("{:?}", b.iter().combinations(0).next()); // None
}
```

https://www.wolframalpha.com/input/?i=0+choose+0
https://www.wolframalpha.com/input/?i=1+choose+0


Discussion / hints:
#174 solves (n, 0), but it seems not to work for (0,0)

Fix patch:
diff --git a/src/combinations.rs b/src/combinations.rs
index 61833cecd..ebd0f947f 100644
--- a/src/combinations.rs
+++ b/src/combinations.rs
@@ -51,13 +51,11 @@ impl<I> Iterator for Combinations<I>
     type Item = Vec<I::Item>;
     fn next(&mut self) -> Option<Self::Item> {
         let mut pool_len = self.pool.len();
-        if self.pool.is_done() {
-            if pool_len == 0 || self.k > pool_len {
-                return None;
-            }
-        }
 
         if self.first {
+            if self.pool.is_done() {
+                return None;
+            }
             self.first = false;
         } else if self.k == 0 {
             return None;
diff --git a/src/combinations_with_replacement.rs b/src/combinations_with_replacement.rs
index 499ccf70d..85629614a 100644
--- a/src/combinations_with_replacement.rs
+++ b/src/combinations_with_replacement.rs
@@ -66,7 +66,7 @@ where
         // If this is the first iteration, return early
         if self.first {
             // In empty edge cases, stop iterating immediately
-            return if self.k == 0 || self.pool.is_done() {
+            return if self.k != 0 && !self.pool.get_next() {
                 None
             // Otherwise, yield the initial state
             } else {
@@ -77,8 +77,7 @@ where
 
         // Check if we need to consume more from the iterator
         // This will run while we increment our first index digit
-        if !self.pool.is_done() {
-            self.pool.get_next();
+        if self.pool.get_next() {
             self.max_index = self.pool.len() - 1;
         }
 
diff --git a/src/lazy_buffer.rs b/src/lazy_buffer.rs
index 09a8cd956..ce5521d94 100644
--- a/src/lazy_buffer.rs
+++ b/src/lazy_buffer.rs
@@ -12,19 +12,10 @@ where
     I: Iterator,
 {
     pub fn new(it: I) -> LazyBuffer<I> {
-        let mut it = it;
-        let mut buffer = Vec::new();
-        let done;
-        if let Some(first) = it.next() {
-            buffer.push(first);
-            done = false;
-        } else {
-            done = true;
-        }
         LazyBuffer {
             it: it,
-            done: done,
-            buffer: buffer,
+            done: false,
+            buffer: Vec::new(),
         }
     }
 


Test patch:
diff --git a/tests/test_std.rs b/tests/test_std.rs
index 4f48c55cf..adcdec82c 100644
--- a/tests/test_std.rs
+++ b/tests/test_std.rs
@@ -599,6 +599,13 @@ fn combinations_of_too_short() {
 #[test]
 fn combinations_zero() {
     it::assert_equal((1..3).combinations(0), vec![vec![]]);
+    it::assert_equal((0..0).combinations(0), vec![vec![]]);
+}
+
+#[test]
+fn permutations_zero() {
+    it::assert_equal((1..3).permutations(0), vec![vec![]]);
+    it::assert_equal((0..0).permutations(0), vec![vec![]]);
 }
 
 #[test]
@@ -620,7 +627,12 @@ fn combinations_with_replacement() {
     // Zero size
     it::assert_equal(
         (0..3).combinations_with_replacement(0),
-        <Vec<Vec<_>>>::new(),
+        vec![vec![]],
+    );
+    // Zero size on empty pool
+    it::assert_equal(
+        (0..0).combinations_with_replacement(0),
+        vec![vec![]],
     );
     // Empty pool
     it::assert_equal(