future_by_example/lib.rs
1//! This document is intended to let readers start working with Rust's `Future` quickly. Some other
2//! useful reading includes:
3//!
4//! - [The official Tokio documentation][tokio]
5//! - [Zero-cost futures in Rust][zero]
6//! - [Tokio Internals: Understanding Rust's asynchronous I/O framework from the bottom up][internals]
7//!
8//! [tokio]: https://tokio.rs/
9//! [zero]: https://aturon.github.io/blog/2016/08/11/futures/
10//! [internals]: https://cafbit.com/post/tokio_internals/
11//!
12//! # `Future`
13//!
14//! The [`Future` trait][future] from [`futures`][futures] represents an asynchronous operation that
15//! can fail or succeed, producing a value either way. It is like an async version of
16//! [`Result`][result]. This document assumes that the reader is familiar with `Result`, which is
17//! [covered][result in trpl] in the second edition of *The Rust Programming Language*.
18//!
19//! One of the most common questions about `Future` seems to be, "how do I get the value out of it?"
20//! The easiest way to do this is to call the `wait` method. This runs the `Future` in the current
21//! thread, blocking all other work until it is finished.
22//!
23//! This is not frequently the best way to run a `Future`, because no other work can happen
24//! until the `Future` completes, which completely defeats the point of using asynchronous
25//! programming in the first place. However, it can be useful in unit tests, when debugging, or at
26//! the top level of a simple application.
27//!
28//! See the section on reactors for better ways to run a `Future`.
29//!
30//! [future]: https://docs.rs/futures/*/futures/future/trait.Future.html
31//! [futures]: https://docs.rs/futures
32//! [result]: https://doc.rust-lang.org/std/result/
33//! [result in trpl]: https://doc.rust-lang.org/book/second-edition/ch09-02-recoverable-errors-with-result.html
34//!
35//! ```rust
36//! extern crate futures;
37//! extern crate future_by_example;
38//!
39//! fn main() {
40//! use futures::Future;
41//! use future_by_example::new_example_future;
42//!
43//! let future = new_example_future();
44//!
45//! let expected = Ok(2);
46//! assert_eq!(future.wait(), expected);
47//! }
48//! ```
49//!
50//! A `Future` can be modified using many functions analogous to those of `Result`, such as `map`,
51//! `map_err`, and `then`. Here's `map`:
52//!
53//! ```rust
54//! extern crate futures;
55//! extern crate future_by_example;
56//!
57//! fn main() {
58//! use futures::Future;
59//! use future_by_example::new_example_future;
60//!
61//! let future = new_example_future();
62//! let mapped = future.map(|i| i * 3);
63//!
64//! let expected = Ok(6);
65//! assert_eq!(mapped.wait(), expected);
66//! }
67//! ```
68//!
69//! Like a `Result`, two `Future`s can be combined using `and_then` and `or_else`:
70//!
71//! ```rust
72//! extern crate futures;
73//! extern crate future_by_example;
74//!
75//! fn main() {
76//! use futures::Future;
77//! use future_by_example::{new_example_future, new_example_future_err, ExampleFutureError};
78//!
79//! let good = new_example_future();
80//! let bad = new_example_future_err();
81//! let both = good.and_then(|good| bad);
82//!
83//! let expected = Err(ExampleFutureError::Oops);
84//! assert_eq!(both.wait(), expected);
85//! }
86//! ```
87//!
88//! `Future` also has a lot of functions that have no analog in `Result`. Because we're talking
89//! about aynchronous programming, now we have to choose whether we want to run two independent
90//! operations one after the other (in sequence), or at the same time (in parallel).
91//!
92//! For example, to get the results of two independent `Future`s, we *could* use `and_then` to run
93//! them in sequence. However, that strategy is silly, because we are only making progress on one
94//! `Future` at a time. Why not run both at the same time?
95//!
96//! `Future::join` creates a new `Future` that contains the results of two other `Future`s.
97//! Importantly, both of the input `Future`s can make progress at the same time. The new `Future`
98//! completes only when both input `Future`s complete. There's also `join3`, `join4` and `join5` for
99//! joining larger numbers of `Future`s.
100//!
101//! ```rust
102//! extern crate futures;
103//! extern crate future_by_example;
104//!
105//! fn main() {
106//! use futures::Future;
107//! use futures::future::ok;
108//! use future_by_example::new_example_future;
109//!
110//! let future1 = new_example_future();
111//! let future2 = new_example_future();
112//!
113//! let joined = future1.join(future2);
114//! let (value1, value2) = joined.wait().unwrap();
115//! assert_eq!(value1, value2);
116//! }
117//! ```
118//!
119//! Whereas `join` completes when *both* `Future`s are complete, `select` returns whichever
120//! of two `Future`s completes first. This is useful for implementing timeouts, among other things.
121//! `select2` is like `select` except that the two `Future`s can have different value types.
122//!
123//! # Creating a `Future`
124//!
125//! Many libraries return `Future`s for asynchronous operations such as network calls. Sometimes you
126//! may want to create your own `Future`. Implementing a `Future` from scratch is difficult, but
127//! there are other ways to create futures.
128//!
129//! You can easily create a `Future` from a value that is already available using the `ok` function.
130//! There are similiar `err` and `result` methods.
131//!
132//! ```rust
133//! extern crate futures;
134//!
135//! fn main() {
136//! use futures::Future;
137//! use futures::future::ok;
138//!
139//! // Here I specify the type of the error as (); otherwise the compiler can't infer it
140//! let future = ok::<_, ()>(String::from("hello"));
141//! assert_eq!(Ok(String::from("hello")), future.wait());
142//! }
143//! ```
144//!
145//! # Futures and types
146//! Working with `Future`s tends to produce complex types. For example, the full type of the
147//! expression below is actually:
148//!
149//! ```text
150//! futures::Map<
151//! futures::Map<
152//! futures::Join<
153//! futures::FutureResult<u64, ()>,
154//! futures::FutureResult<u64, ()>
155//! >,
156//! [closure@src/lib.rs:...]>,
157//! [closure@src/lib.rs:...]
158//! >
159//! ```
160//!
161//! That is, for every transformation, we add another layer to the type of our `Future`! This can
162//! sometimes be confusing. In particular, it can be challenging to identify ways to write out the
163//! types that aren't brittle or verbose.
164//!
165//! In order to help the Rust compiler do type inference, below we have specify the type of
166//! `expected`. It's much terser than writing the full type out, and adding another operation won't
167//! break compilation.
168//!
169//! ```rust
170//! extern crate futures;
171//!
172//! fn main() {
173//! use futures::future::ok;
174//! use futures::Future;
175//!
176//! let expected: Result<u64, ()> = Ok(6);
177//! assert_eq!(
178//! ok(5).join(ok(7)).map(|(x, y)| x + y).map(|z| z / 2).wait(),
179//! expected
180//! )
181//! }
182//! ```
183//!
184//! Alternatively, we can make use of `_` to let the Rust compiler infer types for us.
185//!
186//! ```rust
187//! extern crate futures;
188//!
189//! fn main() {
190//! use futures::future::ok;
191//! use futures::Future;
192//! use futures::Map;
193//!
194//! let expected: Result<_, ()> = Ok(6);
195//! let twelve: Map<_, _> = ok(5).join(ok(7)).map(|(x, y)| x + y);
196//! assert_eq!(twelve.map(|z| z / 2).wait(), expected)
197//! }
198//! ```
199//!
200//! Rust requires that all types in function signatures are specified.
201//!
202//! One way to achieve this for functions that return `Future`s is to specify the full return
203//! type in the function signature. However, specifying the exact type can be verbose, brittle, and
204//! difficult.
205//!
206//! It would be nice to be able to define a function like this:
207//!
208//! ```text
209//! fn make_twelve() -> Future<Item=u64, Error=()> {
210//! unimplemented!()
211//! }
212//! ```
213//!
214//! However, the compiler doesn't like that:
215//!
216//! ```text
217//! error[E0277]: the trait bound `futures::Future<Item=u64, Error=()>: std::marker::Sized` is not satisfied
218//! --> src/lib.rs:119:13
219//! |
220//! 119 | let twelve = make_twelve();
221//! | ^^^^^^ `futures::Future<Item=u64, Error=()>` does not have a constant size known at compile-time
222//! |
223//! = help: the trait `std::marker::Sized` is not implemented for `futures::Future<Item=u64, Error=()>`
224//! = note: all local variables must have a statically known size
225//! ```
226//!
227//! This can be solved by wrapping the return type in a `Box`. One day, this will be solved in a
228//! more elegant way with the currently unstable [impl Trait][impl trait] functionality.
229//!
230//![impl trait]: https://internals.rust-lang.org/t/help-test-impl-trait/6516
231//!
232//! ```rust
233//! extern crate futures;
234//!
235//! fn main() {
236//! use futures::Future;
237//! use futures::future::ok;
238//!
239//! fn make_twelve() -> Box<Future<Item=u64, Error=()>> {
240//!
241//! ok(5).join(ok(7)).map(|(x, y)| x + y).boxed()
242//! }
243//!
244//! let twelve = make_twelve();
245//! assert_eq!(twelve.map(|z| z / 2).wait(), Ok(6))
246//! }
247//! ```
248//!
249//! Unlike functions, closures do not require all types in their signatures to be explicitly
250//! defined, so they don't need to be wrapped in a `Box`.
251//!
252//! ```rust
253//! extern crate futures;
254//!
255//! fn main() {
256//! use futures::Future;
257//!
258//! let make_twelve = || {
259//! use futures::future::ok;
260//!
261//! // We don't need to put our `Future` inside of a `Box` here.
262//! ok(5).join(ok(7)).map(|(x, y)| x + y)
263//! };
264//!
265//! let expected: Result<u64, ()> = Ok(6);
266//! let twelve = make_twelve();
267//! assert_eq!(twelve.map(|z| z / 2).wait(), expected)
268//! }
269//! ```
270//!
271//! # A more powerful way to run Futures
272//! Composing a bunch of `Futures` into a single `Future` and calling `wait` on it is a simple and
273//! easy method as long as you only need to run a single `Future` at a time. However, if you only
274//! need to run a single `Future` at a time, perhaps you don't need the `futures` crate in the first
275//! place! The `futures` crate promises to efficiently juggle many concurrent tasks, so let's
276//! see how that might work.
277//!
278//! The [`tokio-core`][tokio-core] crate has a struct called [`Core`][core] which can run multiple
279//! `Future`s concurrently. `Core::run` runs a `Future`, returning its value. Unlike `Future::wait`,
280//! though, it allows the `Core` to make progress on executing other `Future` objects while `run`
281//! running. The `Future` in `Core::run` is the main event loop, and it may request that new
282//! `Future`s be run by calling `Handle::spawn`. Note that the `Future`s run by `spawn` don't get to
283//! return a value; they exist only to perform side effects.
284//!
285//! [tokio-core]: https://docs.rs/tokio-core
286//! [core]: https://docs.rs/tokio-core/*/tokio_core/reactor/struct.Core.html
287//!
288//! ```rust
289//! extern crate futures;
290//! extern crate tokio_core;
291//!
292//! fn main() {
293//! use tokio_core::reactor::Core;
294//! use futures::future::lazy;
295//!
296//! let mut core = Core::new().unwrap();
297//! let handle = core.handle();
298//! let future = lazy(|| {
299//! handle.spawn(lazy(|| {
300//! Ok(()) // Ok(()) implements FromResult
301//! }));
302//! Ok(2)
303//! });
304//! let expected: Result<_, ()> = Ok(2usize);
305//! assert_eq!(core.run(future), expected);
306//! }
307//! ```
308//!
309#![deny(warnings)]
310
311extern crate futures;
312extern crate tokio_core;
313
314use futures::future::FutureResult;
315
316// Ideally impl Trait will prevent us from needing to be aware of FutureResult.
317type ExampleFuture = FutureResult<usize, ExampleFutureError>;
318
319#[derive(Debug, PartialEq)]
320pub enum ExampleFutureError {
321 Oops,
322}
323
324pub fn new_example_future() -> ExampleFuture {
325 futures::future::ok(2)
326}
327
328pub fn new_example_future_err() -> ExampleFuture {
329 futures::future::err(ExampleFutureError::Oops)
330}