Skip to content

Commit ea51c8b

Browse files
authored
Rollup merge of rust-lang#59362 - pnkfelix:demo-from-iterator-short-circuiting, r=Centril
Demo `FromIterator` short-circuiting while looking at a FIXME in `FromIterator for Option` and `FromIterator for Result`, I realized that the current documentation does not have example code showing exactly what is meant by "no further elements are taken." The code snippets provided here are meant to correct that.
2 parents f9ae15f + 0e83e96 commit ea51c8b

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

src/libcore/option.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,6 +1315,26 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
13151315
/// Since the last element is zero, it would underflow. Thus, the resulting
13161316
/// value is `None`.
13171317
///
1318+
/// Here is a variation on the previous example, showing that no
1319+
/// further elements are taken from `iter` after the first `None`.
1320+
///
1321+
/// ```
1322+
/// let items = vec![3_u16, 2, 1, 10];
1323+
///
1324+
/// let mut shared = 0;
1325+
///
1326+
/// let res: Option<Vec<u16>> = items
1327+
/// .iter()
1328+
/// .map(|x| { shared += x; x.checked_sub(2) })
1329+
/// .collect();
1330+
///
1331+
/// assert_eq!(res, None);
1332+
/// assert_eq!(shared, 6);
1333+
/// ```
1334+
///
1335+
/// Since the third element caused an underflow, no further elements were taken,
1336+
/// so the final value of `shared` is 6 (= `3 + 2 + 1`), not 16.
1337+
///
13181338
/// [`Iterator`]: ../iter/trait.Iterator.html
13191339
#[inline]
13201340
fn from_iter<I: IntoIterator<Item=Option<A>>>(iter: I) -> Option<V> {

src/libcore/result.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,34 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
12021202
/// ).collect();
12031203
/// assert_eq!(res, Ok(vec![2, 3]));
12041204
/// ```
1205+
///
1206+
/// Here is another example that tries to subtract one from another list
1207+
/// of integers, this time checking for underflow:
1208+
///
1209+
/// ```
1210+
/// let v = vec![1, 2, 0];
1211+
/// let res: Result<Vec<u32>, &'static str> = v.iter().map(|x: &u32|
1212+
/// x.checked_sub(1).ok_or("Underflow!")
1213+
/// ).collect();
1214+
/// assert_eq!(res, Err("Underflow!"));
1215+
/// ```
1216+
///
1217+
/// Here is a variation on the previous example, showing that no
1218+
/// further elements are taken from `iter` after the first `Err`.
1219+
///
1220+
/// ```
1221+
/// let v = vec![3, 2, 1, 10];
1222+
/// let mut shared = 0;
1223+
/// let res: Result<Vec<u32>, &'static str> = v.iter().map(|x: &u32| {
1224+
/// shared += x;
1225+
/// x.checked_sub(2).ok_or("Underflow!")
1226+
/// }).collect();
1227+
/// assert_eq!(res, Err("Underflow!"));
1228+
/// assert_eq!(shared, 6);
1229+
/// ```
1230+
///
1231+
/// Since the third element caused an underflow, no further elements were taken,
1232+
/// so the final value of `shared` is 6 (= `3 + 2 + 1`), not 16.
12051233
#[inline]
12061234
fn from_iter<I: IntoIterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {
12071235
// FIXME(#11084): This could be replaced with Iterator::scan when this

0 commit comments

Comments
 (0)