Skip to content

Commit aa3ee1d

Browse files
Rollup merge of rust-lang#35810 - matthew-piziak:fn-trait-example, r=steveklabnik
improve documentation for `Fn*` traits This PR is not yet a serious attempt at contribution. Rather, I'm opening this for discussion. 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
2 parents ff45e61 + 67b9cd3 commit aa3ee1d

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

@@ -2200,6 +2267,35 @@ impl<'a, T: ?Sized> DerefMut for &'a mut T {
22002267
}
22012268

22022269
/// A version of the call operator that takes an immutable receiver.
2270+
///
2271+
/// # Examples
2272+
///
2273+
/// Closures automatically implement this trait, which allows them to be
2274+
/// invoked. Note, however, that `Fn` takes an immutable reference to any
2275+
/// captured variables. To take a mutable capture, implement [`FnMut`], and to
2276+
/// consume the capture, implement [`FnOnce`].
2277+
///
2278+
/// [`FnMut`]: trait.FnMut.html
2279+
/// [`FnOnce`]: trait.FnOnce.html
2280+
///
2281+
/// ```
2282+
/// let square = |x| x * x;
2283+
/// assert_eq!(square(5), 25);
2284+
/// ```
2285+
///
2286+
/// Closures can also be passed to higher-level functions through a `Fn`
2287+
/// parameter (or a `FnMut` or `FnOnce` parameter, which are supertraits of
2288+
/// `Fn`).
2289+
///
2290+
/// ```
2291+
/// fn call_with_one<F>(func: F) -> usize
2292+
/// where F: Fn(usize) -> usize {
2293+
/// func(1)
2294+
/// }
2295+
///
2296+
/// let double = |x| x * 2;
2297+
/// assert_eq!(call_with_one(double), 2);
2298+
/// ```
22032299
#[lang = "fn"]
22042300
#[stable(feature = "rust1", since = "1.0.0")]
22052301
#[rustc_paren_sugar]
@@ -2211,6 +2307,40 @@ pub trait Fn<Args> : FnMut<Args> {
22112307
}
22122308

22132309
/// A version of the call operator that takes a mutable receiver.
2310+
///
2311+
/// # Examples
2312+
///
2313+
/// Closures that mutably capture variables automatically implement this trait,
2314+
/// which allows them to be invoked.
2315+
///
2316+
/// ```
2317+
/// let mut x = 5;
2318+
/// {
2319+
/// let mut square_x = || x *= x;
2320+
/// square_x();
2321+
/// }
2322+
/// assert_eq!(x, 25);
2323+
/// ```
2324+
///
2325+
/// Closures can also be passed to higher-level functions through a `FnMut`
2326+
/// parameter (or a `FnOnce` parameter, which is a supertrait of `FnMut`).
2327+
///
2328+
/// ```
2329+
/// fn do_twice<F>(mut func: F)
2330+
/// where F: FnMut()
2331+
/// {
2332+
/// func();
2333+
/// func();
2334+
/// }
2335+
///
2336+
/// let mut x: usize = 1;
2337+
/// {
2338+
/// let add_two_to_x = || x += 2;
2339+
/// do_twice(add_two_to_x);
2340+
/// }
2341+
///
2342+
/// assert_eq!(x, 5);
2343+
/// ```
22142344
#[lang = "fn_mut"]
22152345
#[stable(feature = "rust1", since = "1.0.0")]
22162346
#[rustc_paren_sugar]
@@ -2222,6 +2352,41 @@ pub trait FnMut<Args> : FnOnce<Args> {
22222352
}
22232353

22242354
/// A version of the call operator that takes a by-value receiver.
2355+
///
2356+
/// # Examples
2357+
///
2358+
/// By-value closures automatically implement this trait, which allows them to
2359+
/// be invoked.
2360+
///
2361+
/// ```
2362+
/// let x = 5;
2363+
/// let square_x = move || x * x;
2364+
/// assert_eq!(square_x(), 25);
2365+
/// ```
2366+
///
2367+
/// By-value Closures can also be passed to higher-level functions through a
2368+
/// `FnOnce` parameter.
2369+
///
2370+
/// ```
2371+
/// fn consume_with_relish<F>(func: F)
2372+
/// where F: FnOnce() -> String
2373+
/// {
2374+
/// // `func` consumes its captured variables, so it cannot be run more
2375+
/// // than once
2376+
/// println!("Consumed: {}", func());
2377+
///
2378+
/// println!("Delicious!");
2379+
///
2380+
/// // Attempting to invoke `func()` again will throw a `use of moved
2381+
/// // value` error for `func`
2382+
/// }
2383+
///
2384+
/// let x = String::from("x");
2385+
/// let consume_and_return_x = move || x;
2386+
/// consume_with_relish(consume_and_return_x);
2387+
///
2388+
/// // `consume_and_return_x` can no longer be invoked at this point
2389+
/// ```
22252390
#[lang = "fn_once"]
22262391
#[stable(feature = "rust1", since = "1.0.0")]
22272392
#[rustc_paren_sugar]

0 commit comments

Comments
 (0)