From 653bcc8ad20320742e2011b4ad009b28767bcae2 Mon Sep 17 00:00:00 2001 From: Lukas Lueg Date: Mon, 18 Jan 2021 20:40:25 +0100 Subject: [PATCH] Expand docs on Iterator::intersperse --- library/core/src/iter/adapters/intersperse.rs | 10 ++-- library/core/src/iter/traits/iterator.rs | 51 +++++++++++++++++-- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/library/core/src/iter/adapters/intersperse.rs b/library/core/src/iter/adapters/intersperse.rs index 1d01e9b5fb7..4a40f8809ae 100644 --- a/library/core/src/iter/adapters/intersperse.rs +++ b/library/core/src/iter/adapters/intersperse.rs @@ -151,12 +151,10 @@ fn intersperse_size_hint(iter: &I, needs_sep: bool) -> (usize, Option) { let (lo, hi) = iter.size_hint(); let next_is_elem = !needs_sep; - let lo = lo.saturating_sub(next_is_elem as usize).saturating_add(lo); - let hi = match hi { - Some(hi) => hi.saturating_sub(next_is_elem as usize).checked_add(hi), - None => None, - }; - (lo, hi) + ( + lo.saturating_sub(next_is_elem as usize).saturating_add(lo), + hi.and_then(|hi| hi.saturating_sub(next_is_elem as usize).checked_add(hi)), + ) } fn intersperse_fold( diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 83d339d8f40..e3b2c394e54 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -569,9 +569,10 @@ fn zip(self, other: U) -> Zip Zip::new(self, other.into_iter()) } - /// Places a copy of `separator` between all elements. + /// Creates a new iterator which places a copy of `separator` between adjacent + /// items of the original iterator. /// - /// In case the separator does not implement [`Clone`] or needs to be + /// In case `separator` does not implement [`Clone`] or needs to be /// computed every time, use [`intersperse_with`]. /// /// # Examples @@ -581,6 +582,19 @@ fn zip(self, other: U) -> Zip /// ``` /// #![feature(iter_intersperse)] /// + /// let mut a = [0, 1, 2].iter().intersperse(&100); + /// assert_eq!(a.next(), Some(&0)); // The first element from `a`. + /// assert_eq!(a.next(), Some(&100)); // The separator. + /// assert_eq!(a.next(), Some(&1)); // The next element from `a`. + /// assert_eq!(a.next(), Some(&100)); // The separator. + /// assert_eq!(a.next(), Some(&2)); // The last element from `a`. + /// assert_eq!(a.next(), None); // The iterator is finished. + /// ``` + /// + /// `intersperse` can be very useful to join an iterator's items using a common element: + /// ``` + /// #![feature(iter_intersperse)] + /// /// let hello = ["Hello", "World", "!"].iter().copied().intersperse(" ").collect::(); /// assert_eq!(hello, "Hello World !"); /// ``` @@ -597,7 +611,16 @@ fn intersperse(self, separator: Self::Item) -> Intersperse Intersperse::new(self, separator) } - /// Places an element generated by `separator` between all elements. + /// Creates a new iterator which places an item generated by `separator` + /// between adjacent items of the original iterator. + /// + /// The closure will be called exactly once each time an item is placed + /// between two adjacent items from the underlying iterator; specifically, + /// the closure is not called if the underlying iterator yields less than + /// two items and after the last item is yielded. + /// + /// If the iterator's item implements [`Clone`], it may be easier to use + /// [`intersperse`]. /// /// # Examples /// @@ -606,14 +629,36 @@ fn intersperse(self, separator: Self::Item) -> Intersperse /// ``` /// #![feature(iter_intersperse)] /// + /// #[derive(PartialEq, Debug)] + /// struct NotClone(usize); + /// + /// let v = vec![NotClone(0), NotClone(1), NotClone(2)]; + /// let mut it = v.into_iter().intersperse_with(|| NotClone(99)); + /// + /// assert_eq!(it.next(), Some(NotClone(0))); // The first element from `v`. + /// assert_eq!(it.next(), Some(NotClone(99))); // The separator. + /// assert_eq!(it.next(), Some(NotClone(1))); // The next element from `v`. + /// assert_eq!(it.next(), Some(NotClone(99))); // The separator. + /// assert_eq!(it.next(), Some(NotClone(2))); // The last element from from `v`. + /// assert_eq!(it.next(), None); // The iterator is finished. + /// ``` + /// + /// `intersperse_with` can be used in situations where the separator needs + /// to be computed: + /// ``` + /// #![feature(iter_intersperse)] + /// /// let src = ["Hello", "to", "all", "people", "!!"].iter().copied(); /// + /// // The closure mutably borrows it's context to generate an item. /// let mut happy_emojis = [" ❤️ ", " 😀 "].iter().copied(); /// let separator = || happy_emojis.next().unwrap_or(" 🦀 "); /// /// let result = src.intersperse_with(separator).collect::(); /// assert_eq!(result, "Hello ❤️ to 😀 all 🦀 people 🦀 !!"); /// ``` + /// [`Clone`]: crate::clone::Clone + /// [`intersperse`]: Iterator::intersperse #[inline] #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] fn intersperse_with(self, separator: G) -> IntersperseWith -- 2.44.0