Add a try_collect() helper method to Iterator · rust-lang/rust@47d5196 (original) (raw)

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>();

`

``

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>();

`

``

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>();

`

``

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>();

`

``

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(&mut self) -> ChangeOutputType<Self::Item, B>

`

``

1853

`+

where

`

``

1854

`+

Self: Sized,

`

``

1855

`+

::Item: Try,

`

``

1856

`+

<::Item as Try>::Residual: Residual,

`

``

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.

``