]> git.lizzy.rs Git - rust.git/blob - src/doc/trpl/generics.md
517a6e6064253295a6292e1a6b2a3e0147f5b2bd
[rust.git] / src / doc / trpl / generics.md
1 % Generics
2
3 Sometimes, when writing a function or data type, we may want it to work for
4 multiple types of arguments. Luckily, Rust has a feature that gives us a better
5 way: generics. Generics are called ‘parametric polymorphism’ in type theory,
6 which means that they are types or functions that have multiple forms (‘poly’
7 is multiple, ‘morph’ is form) over a given parameter (‘parametric’).
8
9 Anyway, enough with type theory, let’s check out some generic code. Rust’s
10 standard library provides a type, `Option<T>`, that’s generic:
11
12 ```rust
13 enum Option<T> {
14     Some(T),
15     None,
16 }
17 ```
18
19 The `<T>` part, which you’ve seen a few times before, indicates that this is
20 a generic data type. Inside the declaration of our enum, wherever we see a `T`,
21 we substitute that type for the same type used in the generic. Here’s an
22 example of using `Option<T>`, with some extra type annotations:
23
24 ```rust
25 let x: Option<i32> = Some(5);
26 ```
27
28 In the type declaration, we say `Option<i32>`. Note how similar this looks to
29 `Option<T>`. So, in this particular `Option`, `T` has the value of `i32`. On
30 the right-hand side of the binding, we do make a `Some(T)`, where `T` is `5`.
31 Since that’s an `i32`, the two sides match, and Rust is happy. If they didn’t
32 match, we’d get an error:
33
34 ```rust,ignore
35 let x: Option<f64> = Some(5);
36 // error: mismatched types: expected `core::option::Option<f64>`,
37 // found `core::option::Option<_>` (expected f64 but found integral variable)
38 ```
39
40 That doesn’t mean we can’t make `Option<T>`s that hold an `f64`! They just have
41 to match up:
42
43 ```rust
44 let x: Option<i32> = Some(5);
45 let y: Option<f64> = Some(5.0f64);
46 ```
47
48 This is just fine. One definition, multiple uses.
49
50 Generics don’t have to only be generic over one type. Consider another type from Rust’s standard library that’s similar, `Result<T, E>`:
51
52 ```rust
53 enum Result<T, E> {
54     Ok(T),
55     Err(E),
56 }
57 ```
58
59 This type is generic over _two_ types: `T` and `E`. By the way, the capital letters
60 can be any letter you’d like. We could define `Result<T, E>` as:
61
62 ```rust
63 enum Result<A, Z> {
64     Ok(A),
65     Err(Z),
66 }
67 ```
68
69 if we wanted to. Convention says that the first generic parameter should be
70 `T`, for ‘type’, and that we use `E` for ‘error’. Rust doesn’t care, however.
71
72 The `Result<T, E>` type is intended to be used to return the result of a
73 computation, and to have the ability to return an error if it didn’t work out.
74
75 ## Generic functions
76
77 We can write functions that take generic types with a similar syntax:
78
79 ```rust
80 fn takes_anything<T>(x: T) {
81     // do something with x
82 }
83 ```
84
85 The syntax has two parts: the `<T>` says “this function is generic over one
86 type, `T`”, and the `x: T` says “x has the type `T`.”
87
88 Multiple arguments can have the same generic type:
89
90 ```rust
91 fn takes_two_of_the_same_things<T>(x: T, y: T) {
92     // ...
93 }
94 ```
95
96 We could write a version that takes multiple types:
97
98 ```rust
99 fn takes_two_things<T, U>(x: T, y: U) {
100     // ...
101 }
102 ```
103
104 Generic functions are most useful with ‘trait bounds’, which we’ll cover in the
105 [section on traits][traits].
106
107 [traits]: traits.html
108
109 ## Generic structs
110
111 You can store a generic type in a `struct` as well:
112
113 ```
114 struct Point<T> {
115     x: T,
116     y: T,
117 }
118
119 let int_origin = Point { x: 0, y: 0 };
120 let float_origin = Point { x: 0.0, y: 0.0 };
121 ```
122
123 Similarly to functions, the `<T>` is where we declare the generic parameters,
124 and we then use `x: T` in the type declaration, too.