From 834f4b770ea58ea39ed18bd50a880e9d61bdc69f Mon Sep 17 00:00:00 2001 From: Taylor Yu Date: Sat, 12 Jun 2021 15:10:58 -0500 Subject: [PATCH] updates based on feedback Make minor wording changes in a few places. Move `filter` to the "transformations" section. Add `zip` methods to the "transformations" section. Clarify the section about `Option` iterators, and add a section about collecting into `Option`. Clarify that for `Result`, `or` and `or_else` can also produce a `Result` having a different type. --- library/core/src/option.rs | 110 +++++++++++++++++++++++++------------ library/core/src/result.rs | 13 +++-- 2 files changed, 83 insertions(+), 40 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index dea32872243..28ea504ec0a 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -132,7 +132,8 @@ //! * [`unwrap_or`] returns the provided default value //! * [`unwrap_or_default`] returns the default value of the type `T` //! (which must implement the [`Default`] trait) -//! * [`unwrap_or_else`] evaluates a provided function +//! * [`unwrap_or_else`] returns the result of evaluating the provided +//! function //! //! [`Default`]: crate::default::Default //! [`expect`]: Option::expect @@ -143,6 +144,9 @@ //! //! ## Transforming contained values //! +//! * [`filter`] calls the provided predicate function on the contained +//! value `t` if the [`Option`] is [`Some(t)`], and returns [`Some(t)`] +//! if the function returns `true`; otherwise, returns [`None`] //! * [`flatten`] removes one level of nesting from an //! [`Option>`] //! * [`map`] transforms [`Some`] to [`Some`] using the provided @@ -159,8 +163,14 @@ //! a value of [`Err`] using the provided function //! * [`transpose`] transposes an [`Option`] of a [`Result`] into a //! [`Result`] of an [`Option`] +//! * [`zip`] returns [`Some((s, o))`] if `self` is [`Some(s)`] and the +//! provided [`Option`] value is [`Some(o)`]; otherwise, returns [`None`] +//! * [`zip_with`] calls the provided function `f` and returns +//! [`Some(f(s, o))`] if `self` is [`Some(s)`] and the provided +//! [`Option`] value is [`Some(o)`]; otherwise, returns [`None`] //! //! [`Err(err)`]: Err +//! [`filter`]: Option::filter //! [`flatten`]: Option::flatten //! [`map`]: Option::map //! [`map_or`]: Option::map_or @@ -168,8 +178,15 @@ //! [`Ok(v)`]: Ok //! [`ok_or`]: Option::ok_or //! [`ok_or_else`]: Option::ok_or_else +//! [`Some(f(s, o))`]: Some +//! [`Some(o)`]: Some +//! [`Some(s)`]: Some +//! [`Some((s, o))`]: Some +//! [`Some(t)`]: Some //! [`Some(v)`]: Some //! [`transpose`]: Option::transpose +//! [`zip`]: Option::zip +//! [`zip_with`]: Option::zip_with //! //! ## Boolean operators //! @@ -196,12 +213,9 @@ //! | [`xor`] | `Some(x)` | `None` | `Some(x)` | //! | [`xor`] | `Some(x)` | `Some(y)` | `None` | //! -//! The [`and_then`], [`filter`], and [`or_else`] methods take a function -//! as input, and only evaluate the function when they need to produce a -//! new value. [`and_then`] and [`or_else`] take a function that produces -//! another [`Option`] value, while [`filter`] takes a predicate that is -//! used to decide whether to pass the [`Some`] value through. Only the -//! [`and_then`] method can produce an [`Option`] value having a +//! The [`and_then`] and [`or_else`] methods take a function as input, and +//! only evaluate the function when they need to produce a new value. Only +//! the [`and_then`] method can produce an [`Option`] value having a //! different inner type `U` than [`Option`]. //! //! | method | self | function input | function result | output | @@ -209,21 +223,17 @@ //! | [`and_then`] | `None` | (not provided) | (not evaluated) | `None` | //! | [`and_then`] | `Some(x)` | `x` | `None` | `None` | //! | [`and_then`] | `Some(x)` | `x` | `Some(y)` | `Some(y)` | -//! | [`filter`] | `None` | (not provided) | (not evaluated) | `None` | -//! | [`filter`] | `Some(x)` | `x` | `false` | `None` | -//! | [`filter`] | `Some(x)` | `x` | `true` | `Some(x)` | //! | [`or_else`] | `None` | (not provided) | `None` | `None` | //! | [`or_else`] | `None` | (not provided) | `Some(y)` | `Some(y)` | //! | [`or_else`] | `Some(x)` | (not provided) | (not evaluated) | `Some(x)` | //! //! [`and`]: Option::and //! [`and_then`]: Option::and_then -//! [`filter`]: Option::filter //! [`or`]: Option::or //! [`or_else`]: Option::or_else //! [`xor`]: Option::xor //! -//! ## Iterators +//! ## Iterating over `Option` //! //! An [`Option`] can be iterated over. This can be helpful if you need an //! iterator that is conditionally empty. The iterator will either produce @@ -241,27 +251,26 @@ //! * [`iter_mut`] produces a mutable reference of type `&mut T` to the //! contained value //! -//! [`Option`] implements the [`FromIterator`] trait, which allows an -//! iterator over [`Option`] values to be collected into an [`Option`] of a -//! collection of each contained value of the original [`Option`] values, -//! or [`None`] if any of the elements was [`None`]. -//! //! [`empty()`]: crate::iter::empty -//! [`FromIterator`]: Option#impl-FromIterator%3COption%3CA%3E%3E //! [`into_iter`]: Option::into_iter //! [`iter`]: Option::iter //! [`iter_mut`]: Option::iter_mut //! [`once(v)`]: crate::iter::once //! [`Some(v)`]: Some //! -//! An iterator over [`Option`] can be useful when chaining iterators: +//! An iterator over [`Option`] can be useful when chaining iterators, for +//! example, to conditionally insert items. (It's not always necessary to +//! explicitly call an iterator constructor: many [`Iterator`] methods that +//! accept other iterators will also accept iterable types that implement +//! [`IntoIterator`], which includes [`Option`].) //! //! ``` //! let yep = Some(42); //! let nope = None; -//! let nums: Vec = (0..4).chain(yep.into_iter()).chain(4..8).collect(); +//! // chain() already calls into_iter(), so we don't have to do so +//! let nums: Vec = (0..4).chain(yep).chain(4..8).collect(); //! assert_eq!(nums, [0, 1, 2, 3, 42, 4, 5, 6, 7]); -//! let nums: Vec = (0..4).chain(nope.into_iter()).chain(4..8).collect(); +//! let nums: Vec = (0..4).chain(nope).chain(4..8).collect(); //! assert_eq!(nums, [0, 1, 2, 3, 4, 5, 6, 7]); //! ``` //! @@ -270,32 +279,63 @@ //! concrete type. Chaining an iterated [`Option`] can help with that. //! //! ``` -//! let yep = Some(42); -//! let nope = None; -//! -//! fn make_iter(opt: Option) -> impl Iterator { -//! (0..4).chain(opt.into_iter()).chain(4..8) +//! fn make_iter(do_insert: bool) -> impl Iterator { +//! // Explicit returns to illustrate return types matching +//! match do_insert { +//! true => return (0..4).chain(Some(42)).chain(4..8), +//! false => return (0..4).chain(None).chain(4..8), +//! } //! } -//! println!("{:?}", make_iter(yep).collect::>()); -//! println!("{:?}", make_iter(nope).collect::>()); +//! println!("{:?}", make_iter(true).collect::>()); +//! println!("{:?}", make_iter(false).collect::>()); //! ``` //! -//! If we try to do the same thing, but using pattern matching, we can't -//! return `impl Iterator` anymore because the concrete types of the return -//! values differ. +//! If we try to do the same thing, but using [`once()`] and [`empty()`], +//! we can't return `impl Iterator` anymore because the concrete types of +//! the return values differ. //! //! ```compile_fail,E0308 //! # use std::iter::{empty, once}; //! // This won't compile because all possible returns from the function //! // must have the same concrete type. -//! fn make_iter(opt: Option) -> impl Iterator { -//! match opt { -//! Some(x) => return (0..4).chain(once(x)).chain(4..8), -//! None => return (0..4).chain(empty()).chain(4..8) +//! fn make_iter(do_insert: bool) -> impl Iterator { +//! // Explicit returns to illustrate return types not matching +//! match x { +//! true => return (0..4).chain(once(42)).chain(4..8), +//! false => return (0..4).chain(empty()).chain(4..8), //! } //! } //! ``` //! +//! [`once()`]: crate::iter::once +//! +//! ## Collecting into `Option` +//! +//! [`Option`] implements the [`FromIterator`] trait, which allows an +//! iterator over [`Option`] values to be collected into an [`Option`] of a +//! collection of each contained value of the original [`Option`] values, +//! or [`None`] if any of the elements was [`None`]. +//! +//! [`FromIterator`]: Option#impl-FromIterator%3COption%3CA%3E%3E +//! +//! ``` +//! let v = vec![Some(2), Some(4), None, Some(8)]; +//! let res: Option> = v.into_iter().collect(); +//! assert_eq!(res, None); +//! let v = vec![Some(2), Some(4), Some(8)]; +//! let res: Option> = v.into_iter().collect(); +//! assert_eq!(res, Some(vec![2, 4, 8])); +//! ``` +//! +//! [`Option`] also implements the [`Product`] and [`Sum`] traits, allowing +//! an iterator over [`Option`] values to provide the +//! [`product`][m.product] and [`sum`][m.sum] methods. +//! +//! [`Product`]: Option#impl-Product%3COption%3CU%3E%3E +//! [`Sum`]: Option#impl-Sum%3COption%3CU%3E%3E +//! [m.product]: crate::iter::Iterator::product +//! [m.sum]: crate::iter::Iterator::sum +//! //! ## Modifying an [`Option`] in-place //! //! These methods return a mutable reference to the contained value of a diff --git a/library/core/src/result.rs b/library/core/src/result.rs index bad75b722b1..444de78a464 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -235,9 +235,10 @@ //! ones that take a function as input (to be lazily evaluated). //! //! The [`and`] and [`or`] methods take another [`Result`] as input, and -//! produce an [`Result`] as output. Only the [`and`] method can produce a +//! produce a [`Result`] as output. The [`and`] method can produce a //! [`Result`] value having a different inner type `U` than -//! [`Result`]. +//! [`Result`]. The [`or`] method can produce a [`Result`] +//! value having a different error type `F` than [`Result`]. //! //! | method | self | input | output | //! |---------|----------|-----------|----------| @@ -249,9 +250,11 @@ //! | [`or`] | `Ok(x)` | (ignored) | `Ok(x)` | //! //! The [`and_then`] and [`or_else`] methods take a function as input, and -//! only evaluate the function when they need to produce a new value. Only -//! the [`and_then`] method can produce an [`Result`] value having a -//! different inner type `U` than [`Result`]. +//! only evaluate the function when they need to produce a new value. The +//! [`and_then`] method can produce a [`Result`] value having a +//! different inner type `U` than [`Result`]. The [`or_else`] method +//! can produce a [`Result`] value having a different error type `F` +//! than [`Result`]. //! //! | method | self | function input | function result | output | //! |--------------|----------|----------------|-----------------|----------|