|
1 | 1 | use crate::cmp::{self, Ordering};
|
2 | 2 | use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try};
|
3 | 3 |
|
| 4 | +use super::super::try_process; |
4 | 5 | use super::super::TrustedRandomAccessNoCoerce;
|
5 | 6 | use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
|
6 | 7 | use super::super::{FlatMap, Flatten};
|
@@ -1777,6 +1778,87 @@ pub trait Iterator {
|
1777 | 1778 | FromIterator::from_iter(self)
|
1778 | 1779 | }
|
1779 | 1780 |
|
| 1781 | + /// Fallibly transforms an iterator into a collection, short circuiting if |
| 1782 | + /// a failure is encountered. |
| 1783 | + /// |
| 1784 | + /// `try_collect()` is a variation of [`collect()`][`collect`] that allows fallible |
| 1785 | + /// conversions during collection. Its main use case is simplifying conversions from |
| 1786 | + /// iterators yielding [`Option<T>`][`Option`] into `Option<Collection<T>>`, or similarly for other [`Try`] |
| 1787 | + /// types (e.g. [`Result`]). |
| 1788 | + /// |
| 1789 | + /// Importantly, `try_collect()` doesn't require that the outer [`Try`] type also implements [`FromIterator`]; |
| 1790 | + /// only the inner type produced on `Try::Output` must implement it. Concretely, |
| 1791 | + /// this means that collecting into `ControlFlow<_, Vec<i32>>` is valid because `Vec<i32>` implements |
| 1792 | + /// [`FromIterator`], even though [`ControlFlow`] doesn't. |
| 1793 | + /// |
| 1794 | + /// Also, if a failure is encountered during `try_collect()`, the iterator is still valid and |
| 1795 | + /// may continue to be used, in which case it will continue iterating starting after the element that |
| 1796 | + /// triggered the failure. See the last example below for an example of how this works. |
| 1797 | + /// |
| 1798 | + /// # Examples |
| 1799 | + /// Successfully collecting an iterator of `Option<i32>` into `Option<Vec<i32>>`: |
| 1800 | + /// ``` |
| 1801 | + /// #![feature(iterator_try_collect)] |
| 1802 | + /// |
| 1803 | + /// let u = vec![Some(1), Some(2), Some(3)]; |
| 1804 | + /// let v = u.into_iter().try_collect::<Vec<i32>>(); |
| 1805 | + /// assert_eq!(v, Some(vec![1, 2, 3])); |
| 1806 | + /// ``` |
| 1807 | + /// |
| 1808 | + /// Failing to collect in the same way: |
| 1809 | + /// ``` |
| 1810 | + /// #![feature(iterator_try_collect)] |
| 1811 | + /// |
| 1812 | + /// let u = vec![Some(1), Some(2), None, Some(3)]; |
| 1813 | + /// let v = u.into_iter().try_collect::<Vec<i32>>(); |
| 1814 | + /// assert_eq!(v, None); |
| 1815 | + /// ``` |
| 1816 | + /// |
| 1817 | + /// A similar example, but with `Result`: |
| 1818 | + /// ``` |
| 1819 | + /// #![feature(iterator_try_collect)] |
| 1820 | + /// |
| 1821 | + /// let u: Vec<Result<i32, ()>> = vec![Ok(1), Ok(2), Ok(3)]; |
| 1822 | + /// let v = u.into_iter().try_collect::<Vec<i32>>(); |
| 1823 | + /// assert_eq!(v, Ok(vec![1, 2, 3])); |
| 1824 | + /// |
| 1825 | + /// let u = vec![Ok(1), Ok(2), Err(()), Ok(3)]; |
| 1826 | + /// let v = u.into_iter().try_collect::<Vec<i32>>(); |
| 1827 | + /// assert_eq!(v, Err(())); |
| 1828 | + /// ``` |
| 1829 | + /// |
| 1830 | + /// Finally, even [`ControlFlow`] works, despite the fact that it |
| 1831 | + /// doesn't implement [`FromIterator`]. Note also that the iterator can |
| 1832 | + /// continue to be used, even if a failure is encountered: |
| 1833 | + /// |
| 1834 | + /// ``` |
| 1835 | + /// #![feature(iterator_try_collect)] |
| 1836 | + /// |
| 1837 | + /// use core::ops::ControlFlow::{Break, Continue}; |
| 1838 | + /// |
| 1839 | + /// let u = [Continue(1), Continue(2), Break(3), Continue(4), Continue(5)]; |
| 1840 | + /// let mut it = u.into_iter(); |
| 1841 | + /// |
| 1842 | + /// let v = it.try_collect::<Vec<_>>(); |
| 1843 | + /// assert_eq!(v, Break(3)); |
| 1844 | + /// |
| 1845 | + /// let v = it.try_collect::<Vec<_>>(); |
| 1846 | + /// assert_eq!(v, Continue(vec![4, 5])); |
| 1847 | + /// ``` |
| 1848 | + /// |
| 1849 | + /// [`collect`]: Iterator::collect |
| 1850 | + #[inline] |
| 1851 | + #[unstable(feature = "iterator_try_collect", issue = "94047")] |
| 1852 | + fn try_collect<B>(&mut self) -> ChangeOutputType<Self::Item, B> |
| 1853 | + where |
| 1854 | + Self: Sized, |
| 1855 | + <Self as Iterator>::Item: Try, |
| 1856 | + <<Self as Iterator>::Item as Try>::Residual: Residual<B>, |
| 1857 | + B: FromIterator<<Self::Item as Try>::Output>, |
| 1858 | + { |
| 1859 | + try_process(self, |i| i.collect()) |
| 1860 | + } |
| 1861 | + |
1780 | 1862 | /// Consumes an iterator, creating two collections from it.
|
1781 | 1863 | ///
|
1782 | 1864 | /// The predicate passed to `partition()` can return `true`, or `false`.
|
|
0 commit comments