magical markdown slides
1---
2theme: default
3author: Learn Rust
4---
5
6# Learn Rust
7
8A quick tour through Rust fundamentals
9
10---
11
12## Comments
13
14Rust supports multiple comment styles:
15
16```rust
17// Line comments look like this
18// and extend multiple lines
19
20/* Block comments
21 /* can be nested. */ */
22
23/// Documentation comments support markdown
24/// # Examples
25/// ```
26/// let five = 5
27/// ```
28```
29
30---
31
32## Functions
33
34Functions use `fn` keyword with type annotations:
35
36```rust
37fn add2(x: i32, y: i32) -> i32 {
38 // Implicit return (no semicolon)
39 x + y
40}
41```
42
43**Key points:**
44
45- `i32` is a 32-bit signed integer
46- Last expression without `;` is the return value
47- Function parameters must have type annotations
48
49---
50
51## Variables
52
53Rust has immutable bindings by default:
54
55```rust
56// Immutable binding
57let x: i32 = 1;
58
59// Type inference works most of the time
60let implicit_x = 1;
61let implicit_f = 1.3;
62
63// Mutable variable
64let mut mutable = 1;
65mutable = 4;
66mutable += 2;
67```
68
69---
70
71## Numbers
72
73Integer and float types with suffixes:
74
75```rust
76// Integer/float suffixes
77let y: i32 = 13i32;
78let f: f64 = 1.3f64;
79
80// Arithmetic
81let sum = x + y + 13;
82```
83
84---
85
86## Strings
87
88Two main string types in Rust:
89
90```rust
91// String slice (&str) - immutable view
92let x: &str = "hello world!";
93
94// String - heap-allocated, growable
95let s: String = "hello world".to_string();
96
97// String slice from String
98let s_slice: &str = &s;
99
100// Printing
101println!("{} {}", f, x);
102```
103
104---
105
106## Arrays and Vectors
107
108Fixed-size arrays and dynamic vectors:
109
110```rust
111// Fixed-size array
112let four_ints: [i32; 4] = [1, 2, 3, 4];
113
114// Dynamic vector
115let mut vector: Vec<i32> = vec![1, 2, 3, 4];
116vector.push(5);
117
118// Slice - immutable view
119let slice: &[i32] = &vector;
120
121// Debug printing
122println!("{:?} {:?}", vector, slice);
123```
124
125---
126
127## Tuples
128
129Fixed-size sets of values of possibly different types:
130
131```rust
132// Tuple declaration
133let x: (i32, &str, f64) = (1, "hello", 3.4);
134
135// Destructuring
136let (a, b, c) = x;
137println!("{} {} {}", a, b, c); // 1 hello 3.4
138
139// Indexing
140println!("{}", x.1); // hello
141```
142
143---
144
145## Structs
146
147Custom data types with named fields:
148
149```rust
150struct Point {
151 x: i32,
152 y: i32,
153}
154
155let origin: Point = Point { x: 0, y: 0 };
156
157// Tuple struct (unnamed fields)
158struct Point2(i32, i32);
159let origin2 = Point2(0, 0);
160```
161
162---
163
164## Enums
165
166Enums can have variants with or without data:
167
168```rust
169// Basic C-like enum
170enum Direction {
171 Left,
172 Right,
173 Up,
174 Down,
175}
176
177let up = Direction::Up;
178
179// Enum with fields
180enum OptionalI32 {
181 AnI32(i32),
182 Nothing,
183}
184
185let two: OptionalI32 = OptionalI32::AnI32(2);
186```
187
188---
189
190## Generics
191
192Type parameters for reusable code:
193
194```rust
195struct Foo<T> { bar: T }
196
197enum Optional<T> {
198 SomeVal(T),
199 NoVal,
200}
201```
202
203The standard library provides `Option<T>` for optional values, replacing null pointers.
204
205---
206
207## Methods
208
209Functions associated with types:
210
211```rust
212impl<T> Foo<T> {
213 // Borrowed self
214 fn bar(&self) -> &T {
215 &self.bar
216 }
217
218 // Mutably borrowed self
219 fn bar_mut(&mut self) -> &mut T {
220 &mut self.bar
221 }
222
223 // Consumed self
224 fn into_bar(self) -> T {
225 self.bar
226 }
227}
228```
229
230---
231
232## Traits
233
234Interfaces that define shared behavior:
235
236```rust
237trait Frobnicate<T> {
238 fn frobnicate(self) -> Option<T>;
239}
240
241impl<T> Frobnicate<T> for Foo<T> {
242 fn frobnicate(self) -> Option<T> {
243 Some(self.bar)
244 }
245}
246
247let foo = Foo { bar: 1 };
248println!("{:?}", foo.frobnicate()); // Some(1)
249```
250
251---
252
253## Pattern Matching
254
255Powerful control flow with `match`:
256
257```rust
258let foo = OptionalI32::AnI32(1);
259match foo {
260 OptionalI32::AnI32(n) => println!("it's an i32: {}", n),
261 OptionalI32::Nothing => println!("it's nothing!"),
262}
263```
264
265---
266
267## Advanced Pattern Matching
268
269Destructure and use guards:
270
271```rust
272struct FooBar { x: i32, y: OptionalI32 }
273let bar = FooBar { x: 15, y: OptionalI32::AnI32(32) };
274
275match bar {
276 FooBar { x: 0, y: OptionalI32::AnI32(0) } =>
277 println!("The numbers are zero!"),
278 FooBar { x: n, y: OptionalI32::AnI32(m) } if n == m =>
279 println!("The numbers are the same"),
280 FooBar { x: n, y: OptionalI32::AnI32(m) } =>
281 println!("Different numbers: {} {}", n, m),
282 FooBar { x: _, y: OptionalI32::Nothing } =>
283 println!("The second number is Nothing!"),
284}
285```
286
287---
288
289## For Loops
290
291Iterate over arrays and ranges:
292
293```rust
294// Array iteration
295let array = [1, 2, 3];
296for i in array {
297 println!("{}", i);
298}
299
300// Range iteration
301for i in 0u32..10 {
302 print!("{} ", i);
303}
304// prints: 0 1 2 3 4 5 6 7 8 9
305```
306
307---
308
309## If Expressions
310
311`if` can be used as an expression:
312
313```rust
314if 1 == 1 {
315 println!("Maths is working!");
316} else {
317 println!("Oh no...");
318}
319
320// if as expression
321let value = if true {
322 "good"
323} else {
324 "bad"
325};
326```
327
328---
329
330## Loops
331
332Multiple loop constructs:
333
334```rust
335// while loop
336while condition {
337 println!("Looping...");
338 break // Exit the loop
339}
340
341// Infinite loop
342loop {
343 println!("Hello!");
344 break // Must break explicitly
345}
346```
347
348---
349
350## Owned Pointers (Box)
351
352`Box<T>` provides heap allocation with single ownership:
353
354```rust
355let mut mine: Box<i32> = Box::new(3);
356*mine = 5; // dereference
357
358// Ownership transfer (move)
359let mut now_its_mine = mine;
360*now_its_mine += 2;
361
362println!("{}", now_its_mine); // 7
363// println!("{}", mine); // Error! moved
364```
365
366When `Box` goes out of scope, memory is automatically deallocated.
367
368---
369
370## Immutable References
371
372Borrowing without transferring ownership:
373
374```rust
375let mut var = 4;
376var = 3;
377let ref_var: &i32 = &var;
378
379println!("{}", var); // Still works!
380println!("{}", *ref_var); // 3
381
382// var = 5; // Error! var is borrowed
383// *ref_var = 6; // Error! immutable reference
384
385ref_var; // Use the reference
386var = 2; // Borrow ended, can mutate again
387```
388
389---
390
391## Mutable References
392
393Exclusive mutable access:
394
395```rust
396let mut var2 = 4;
397let ref_var2: &mut i32 = &mut var2;
398*ref_var2 += 2;
399
400println!("{}", *ref_var2); // 6
401
402// var2 = 2; // Error! var2 is mutably borrowed
403
404ref_var2; // Use ends here
405// Now var2 can be used again
406```
407
408**Key rule:** Either many immutable references OR one mutable reference.
409
410---
411
412## Memory Safety
413
414Rust's borrow checker ensures:
415
416- No use after free
417- No double free
418- No data races
419- No dangling pointers
420
421All at **compile time** with **zero runtime cost**.
422
423---
424
425## Next Steps
426
427- Explore the [Rust Book](https://doc.rust-lang.org/book/)
428- Try [Rust by Example](https://doc.rust-lang.org/rust-by-example/)
429- Practice with [Rustlings](https://github.com/rust-lang/rustlings)
430- Join the [Rust community](https://www.rust-lang.org/community)
431
432---
433
434## Thank You
435
436Happy Rusting!