Skip to content

Commit c44f64c

Browse files
committed
push for review
1 parent 169dfa2 commit c44f64c

5 files changed

Lines changed: 206 additions & 25 deletions

File tree

courses/rust_essentials/100_generics.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,6 @@ Generics
3434

3535
.. include:: 100_generics/01_introduction.rst
3636
.. include:: 100_generics/02_generics.rst
37-
.. include:: 100_generics/03_generics_and_traits.rst
37+
.. include:: 100_generics/03_constraints_and_properties.rst
3838
.. include:: 100_generics/98_lab.rst
3939
.. include:: 100_generics/99_summary.rst

courses/rust_essentials/100_generics/01_introduction.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ Introduction
66
Topics Covered
77
----------------
88

9-
- **Generic data types**
9+
- **Generic Data Types**
1010

1111
- Definition and instantiation
1212

13-
- **Constraints and properties**
13+
- **Constraints and Properties**
1414

15-
- **Generic traits**
15+
- **Generic Traits**
1616

1717

1818
-------------------------
@@ -31,7 +31,7 @@ The Notion of a Pattern
3131
(right, left)
3232
}
3333
34-
* It would be nice to extract these properties in some common pattern, and then just replace the parts that need to be replaced
34+
* A common pattern can be extracted, with only some parts to replace
3535

3636
.. code:: Rust
3737

courses/rust_essentials/100_generics/02_generics.rst

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,11 @@ Generic Data Type
1919
fn Swap<T> (l: T, r: T) -> (T, T) {
2020
(r, l)
2121
}
22-
2322

2423
- :rust:`T` (the generic type parameter) means an :rust:`Swap` can wrap any type
2524

2625
- :rust:`Swap<i32>`, :rust:`Swap<f64>` etc
2726

28-
29-
3027
------------
3128
Be Generic
3229
------------
@@ -68,7 +65,6 @@ Constructs that can be made generic
6865
-- JBE : very all options are present in examples
6966
-- Add Examples ?
7067

71-
7268
----------------
7369
Type Inference
7470
----------------
@@ -92,7 +88,6 @@ Type Inference
9288
9389
- Type is **infered** at compile-time from the context
9490

95-
9691
-----------------------
9792
Multiple Generic Type
9893
-----------------------
@@ -109,9 +104,4 @@ Constructs can have multiple generic data types
109104
let both_integer = Point { x: 5, y: 10 };
110105
let both_float = Point { x: 1.0, y: 4.0 };
111106
let integer_and_float = Point { x: 5, y: 4.0 };
112-
113-
114-
115-
116-
117-
107+

courses/rust_essentials/100_generics/03_constraints_and_properties.rst

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ Trait Bounds
2323
println!("{}", item); // Only works if 'T' implements Display
2424
}
2525
26-
2726
--------------------
2827
Adding Constraints
2928
--------------------
@@ -37,7 +36,7 @@ Adding a trait to a generic object gives it more functionalities
3736
item < 10
3837
}
3938
40-
:error:`ERROR: "binary operation '<' cannot be applied to type 'T'"`
39+
:error:`error[E0369]: binary operation '<' cannot be applied to type 'T'`
4140

4241
.. code:: rust
4342
@@ -73,7 +72,7 @@ Satisfying Constraints
7372
Trait Bounds Generics
7473
-----------------------
7574

76-
- User defined traits can be constraints for a generic function
75+
- User-defined traits can be constraints for a generic function
7776

7877
.. code:: rust
7978
@@ -140,8 +139,6 @@ Multiple Traits
140139
U: Debug + PartialOrd
141140
{ ... }
142141
143-
144-
145142
----------------
146143
Generic Traits
147144
----------------
@@ -163,9 +160,8 @@ Generic Traits
163160
}
164161
// Rule for converting Minutes to a String
165162
impl Transform<String> for Minutes {
166-
fn convert(&self) -> String { format!("{} minutes", self.0) }
163+
fn convert(&self) -> String { format!("{} min", self.0) }
167164
168-
169165
-----------------------------
170166
"derive" Macro and Generics
171167
-----------------------------
@@ -192,5 +188,4 @@ Generic Traits
192188
// Secret doesn't implement Debug, derive macro fails
193189
}
194190
:error:`ERROR: "Box<Secret> doesn't implement Debug"`
195-
196-
191+
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
============================
2+
Constraints and Properties
3+
============================
4+
5+
--------------
6+
Trait Bounds
7+
--------------
8+
9+
- Generic data :rust:`<T>` has almost no limitations
10+
11+
- Compiler will restrict what can be done with :rust:`<T>`
12+
- Doesn't know if it can do math, order or anything else
13+
14+
- Traits are the **fine print** on a generic **contract**
15+
16+
- Ensure the logic only executes on types that "fit" the requirements
17+
18+
- Added in the :rust:`<>` next to the type
19+
20+
.. code:: rust
21+
22+
fn print_it<T: std::fmt::Display>(item: T) {
23+
println!("{}", item); // Only works if 'T' implements Display
24+
}
25+
26+
27+
--------------------
28+
Adding Constraints
29+
--------------------
30+
31+
Adding a trait to a generic object gives it more functionalities
32+
33+
.. code:: rust
34+
35+
// Compiler: "What if T is a name? Is 'Bob' < 10?"
36+
fn is_small<T>(item: T) -> bool {
37+
item < 10
38+
}
39+
40+
:error:`ERROR: "binary operation '<' cannot be applied to type 'T'"`
41+
42+
.. code:: rust
43+
44+
fn smaller<T: PartialOrd>(item: T, max_v: T) -> bool {
45+
item < max_v
46+
}
47+
48+
------------------------
49+
Satisfying Constraints
50+
------------------------
51+
52+
- Adding a trait restrict types that satisfy the generic contract
53+
54+
.. code:: rust
55+
56+
struct Vegetable;
57+
58+
fn smaller<T: PartialOrd>(item: T, threshold: T) -> bool {
59+
item < threshold
60+
}
61+
62+
fn main() {
63+
let potato : Vegetable;
64+
let sweet_potato : Vegetable;
65+
println!("{}", smaller(5, 10));
66+
println!("{}", smaller(1.5, 10.0));
67+
println!("{}", smaller(potato , sweet_potato));
68+
}
69+
70+
:error:`error[E0277]: can't compare 'vegetable' with 'vegetable'`
71+
72+
-----------------------
73+
Trait Bounds Generics
74+
-----------------------
75+
76+
- User defined traits can be constraints for a generic function
77+
78+
.. code:: rust
79+
80+
trait Speak {
81+
fn say_hello(&self);
82+
}
83+
84+
struct Dog;
85+
86+
impl Speak for Dog {
87+
fn say_hello(&self) {
88+
println!("Woof!");
89+
}
90+
}
91+
92+
// This function ONLY accepts types that can 'Speak'
93+
fn make_it_speak<T: Speak>(item: T) {
94+
item.say_hello();
95+
}
96+
97+
fn main() {
98+
let pet = Dog;
99+
make_it_speak(pet); // Output: Woof!
100+
}
101+
102+
------------------
103+
Turbofish "::<>"
104+
------------------
105+
106+
- Usually the compiler determines the type to use from context
107+
108+
- Sometimes there is *ambiguity*
109+
110+
.. code:: rust
111+
112+
// Vec<T> is a generic struct
113+
// Vec defines an associated function called 'new'
114+
// Error: "type annotations needed"
115+
// The compiler knows it's a Vec, but a Vec of what?
116+
let x = Vec::new();
117+
118+
- The turbofish :rust:`::<>` syntax is used to dispell ambiguity
119+
120+
.. code:: rust
121+
122+
// The Turbofish dispels the mystery!
123+
let x = Vec::<i32>::new();
124+
125+
-----------------
126+
Multiple Traits
127+
-----------------
128+
129+
- Can have multiple trait bounds
130+
131+
- Using the :rust:`+` operator
132+
133+
- :rust:`where` clause can be used for better visibility
134+
135+
.. code:: rust
136+
137+
fn complex_function<T, U>(t: T, u: U)
138+
where
139+
T: Display + Clone,
140+
U: Debug + PartialOrd
141+
{ ... }
142+
143+
144+
145+
----------------
146+
Generic Traits
147+
----------------
148+
149+
- Traits can be made generic
150+
151+
- Allows the same trait to behave differently with each type
152+
153+
.. code:: rust
154+
155+
// T is the "Target" type we want to turn into
156+
trait Transform<T> {
157+
fn convert(&self) -> T;
158+
}
159+
struct Minutes(i32);
160+
// Rule for converting Minutes to Seconds
161+
impl Transform<i32> for Minutes {
162+
fn convert(&self) -> i32 { self.0 * 60 }
163+
}
164+
// Rule for converting Minutes to a String
165+
impl Transform<String> for Minutes {
166+
fn convert(&self) -> String { format!("{} minutes", self.0) }
167+
168+
169+
-----------------------------
170+
"derive" Macro and Generics
171+
-----------------------------
172+
173+
- :rust:`derive` macro can be used on generic struct using standard traits
174+
175+
- Can't be used on generic traits
176+
177+
.. code:: rust
178+
179+
// Compiler assumes T has 'Debug' trait
180+
#[derive(Debug)]
181+
struct Box<T> {
182+
content: T,
183+
}
184+
struct Secret; // Note: No Debug here
185+
186+
fn main() {
187+
let good_box = Box { content: 42 };
188+
println!("{:?}", good_box); // Works (i32 is Debug)
189+
190+
let bad_box = Box { content: Secret };
191+
// ERROR: "Box<Secret> doesn't implement Debug"
192+
// Secret doesn't implement Debug, derive macro fails
193+
}
194+
:error:`ERROR: "Box<Secret> doesn't implement Debug"`
195+
196+

0 commit comments

Comments
 (0)