Skip to content

Commit 67b9cd3

Browse files
improve documentation for Fn* traits
I can think of a few things we may want to accomplish with the documentation of the `Fn`, `FnMut`, and `FnOnce` traits: - the relationship between these traits and the closures that implement them - examples of non-closure implementations - the relationship between these traits and Rust's ownership semantics add module-level documentation for `Fn*` traits Describe how `Fn*` traits, closure types, and ownership semantics are linked, and provide examples of higher-level functions that take `Fn*`s. more examples for `Fn*` traits create correct (though not yet elegant) examples for `FnMut` and `FnOnce` add trait links to module-level documentation third time's a charm! argument -> capture for trait documentation This wording will need to be supported with better examples for capturing eventually. correct `FnOnce` example I also fixed some of the trait wording here to make the concept of capturing clearer; though that still needs more work. replace `x + x` with `x * 2` for `fn double`
1 parent 4901896 commit 67b9cd3

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed

src/libcore/ops.rs

+165
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,73 @@
6868
//! ```
6969
//!
7070
//! See the documentation for each trait for an example implementation.
71+
//!
72+
//! The [`Fn`], [`FnMut`], and [`FnOnce`] traits are implemented by types that can be
73+
//! invoked like functions. Note that `Fn` takes `&self`, `FnMut` takes `&mut
74+
//! self` and `FnOnce` takes `self`. These correspond to the three kinds of
75+
//! methods that can be invoked on an instance: call-by-reference,
76+
//! call-by-mutable-reference, and call-by-value. The most common use of these
77+
//! traits is to act as bounds to higher-level functions that take functions or
78+
//! closures as arguments.
79+
//!
80+
//! [`Fn`]: trait.Fn.html
81+
//! [`FnMut`]: trait.FnMut.html
82+
//! [`FnOnce`]: trait.FnOnce.html
83+
//!
84+
//! Taking a `Fn` as a parameter:
85+
//!
86+
//! ```rust
87+
//! fn call_with_one<F>(func: F) -> usize
88+
//! where F: Fn(usize) -> usize
89+
//! {
90+
//! func(1)
91+
//! }
92+
//!
93+
//! let double = |x| x * 2;
94+
//! assert_eq!(call_with_one(double), 2);
95+
//! ```
96+
//!
97+
//! Taking a `FnMut` as a parameter:
98+
//!
99+
//! ```rust
100+
//! fn do_twice<F>(mut func: F)
101+
//! where F: FnMut()
102+
//! {
103+
//! func();
104+
//! func();
105+
//! }
106+
//!
107+
//! let mut x: usize = 1;
108+
//! {
109+
//! let add_two_to_x = || x += 2;
110+
//! do_twice(add_two_to_x);
111+
//! }
112+
//!
113+
//! assert_eq!(x, 5);
114+
//! ```
115+
//!
116+
//! Taking a `FnOnce` as a parameter:
117+
//!
118+
//! ```rust
119+
//! fn consume_with_relish<F>(func: F)
120+
//! where F: FnOnce() -> String
121+
//! {
122+
//! // `func` consumes its captured variables, so it cannot be run more
123+
//! // than once
124+
//! println!("Consumed: {}", func());
125+
//!
126+
//! println!("Delicious!");
127+
//!
128+
//! // Attempting to invoke `func()` again will throw a `use of moved
129+
//! // value` error for `func`
130+
//! }
131+
//!
132+
//! let x = String::from("x");
133+
//! let consume_and_return_x = move || x;
134+
//! consume_with_relish(consume_and_return_x);
135+
//!
136+
//! // `consume_and_return_x` can no longer be invoked at this point
137+
//! ```
71138
72139
#![stable(feature = "rust1", since = "1.0.0")]
73140

@@ -2027,6 +2094,35 @@ impl<'a, T: ?Sized> DerefMut for &'a mut T {
20272094
}
20282095

20292096
/// A version of the call operator that takes an immutable receiver.
2097+
///
2098+
/// # Examples
2099+
///
2100+
/// Closures automatically implement this trait, which allows them to be
2101+
/// invoked. Note, however, that `Fn` takes an immutable reference to any
2102+
/// captured variables. To take a mutable capture, implement [`FnMut`], and to
2103+
/// consume the capture, implement [`FnOnce`].
2104+
///
2105+
/// [`FnMut`]: trait.FnMut.html
2106+
/// [`FnOnce`]: trait.FnOnce.html
2107+
///
2108+
/// ```
2109+
/// let square = |x| x * x;
2110+
/// assert_eq!(square(5), 25);
2111+
/// ```
2112+
///
2113+
/// Closures can also be passed to higher-level functions through a `Fn`
2114+
/// parameter (or a `FnMut` or `FnOnce` parameter, which are supertraits of
2115+
/// `Fn`).
2116+
///
2117+
/// ```
2118+
/// fn call_with_one<F>(func: F) -> usize
2119+
/// where F: Fn(usize) -> usize {
2120+
/// func(1)
2121+
/// }
2122+
///
2123+
/// let double = |x| x * 2;
2124+
/// assert_eq!(call_with_one(double), 2);
2125+
/// ```
20302126
#[lang = "fn"]
20312127
#[stable(feature = "rust1", since = "1.0.0")]
20322128
#[rustc_paren_sugar]
@@ -2038,6 +2134,40 @@ pub trait Fn<Args> : FnMut<Args> {
20382134
}
20392135

20402136
/// A version of the call operator that takes a mutable receiver.
2137+
///
2138+
/// # Examples
2139+
///
2140+
/// Closures that mutably capture variables automatically implement this trait,
2141+
/// which allows them to be invoked.
2142+
///
2143+
/// ```
2144+
/// let mut x = 5;
2145+
/// {
2146+
/// let mut square_x = || x *= x;
2147+
/// square_x();
2148+
/// }
2149+
/// assert_eq!(x, 25);
2150+
/// ```
2151+
///
2152+
/// Closures can also be passed to higher-level functions through a `FnMut`
2153+
/// parameter (or a `FnOnce` parameter, which is a supertrait of `FnMut`).
2154+
///
2155+
/// ```
2156+
/// fn do_twice<F>(mut func: F)
2157+
/// where F: FnMut()
2158+
/// {
2159+
/// func();
2160+
/// func();
2161+
/// }
2162+
///
2163+
/// let mut x: usize = 1;
2164+
/// {
2165+
/// let add_two_to_x = || x += 2;
2166+
/// do_twice(add_two_to_x);
2167+
/// }
2168+
///
2169+
/// assert_eq!(x, 5);
2170+
/// ```
20412171
#[lang = "fn_mut"]
20422172
#[stable(feature = "rust1", since = "1.0.0")]
20432173
#[rustc_paren_sugar]
@@ -2049,6 +2179,41 @@ pub trait FnMut<Args> : FnOnce<Args> {
20492179
}
20502180

20512181
/// A version of the call operator that takes a by-value receiver.
2182+
///
2183+
/// # Examples
2184+
///
2185+
/// By-value closures automatically implement this trait, which allows them to
2186+
/// be invoked.
2187+
///
2188+
/// ```
2189+
/// let x = 5;
2190+
/// let square_x = move || x * x;
2191+
/// assert_eq!(square_x(), 25);
2192+
/// ```
2193+
///
2194+
/// By-value Closures can also be passed to higher-level functions through a
2195+
/// `FnOnce` parameter.
2196+
///
2197+
/// ```
2198+
/// fn consume_with_relish<F>(func: F)
2199+
/// where F: FnOnce() -> String
2200+
/// {
2201+
/// // `func` consumes its captured variables, so it cannot be run more
2202+
/// // than once
2203+
/// println!("Consumed: {}", func());
2204+
///
2205+
/// println!("Delicious!");
2206+
///
2207+
/// // Attempting to invoke `func()` again will throw a `use of moved
2208+
/// // value` error for `func`
2209+
/// }
2210+
///
2211+
/// let x = String::from("x");
2212+
/// let consume_and_return_x = move || x;
2213+
/// consume_with_relish(consume_and_return_x);
2214+
///
2215+
/// // `consume_and_return_x` can no longer be invoked at this point
2216+
/// ```
20522217
#[lang = "fn_once"]
20532218
#[stable(feature = "rust1", since = "1.0.0")]
20542219
#[rustc_paren_sugar]

0 commit comments

Comments
 (0)