Skip to content

Commit

Permalink
WIP on improving slides
Browse files Browse the repository at this point in the history
  • Loading branch information
hdoordt committed Jun 29, 2023
1 parent 7a2e366 commit c74bb90
Show file tree
Hide file tree
Showing 17 changed files with 205 additions and 159 deletions.
35 changes: 23 additions & 12 deletions slides/A-foundations/basic-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ that variable
```rust
fn main() {
let x: i32 = 20;
// ^^^^^ Type annotation
}
```

Expand Down Expand Up @@ -242,14 +243,14 @@ then the code for b is not executed

```rust
fn main() {
let c = 'z';
let c: char = 'z';
let z = 'ℤ';
let heart_eyed_cat = '😻';
}
```

- A character is a 32-bit unicode scalar value
- Very much unlike C/C++ where char is 8 bits
- A `char` is a 32-bit unicode scalar value
- Very much unlike C/C++ where `char is 8 bits

<!--
- The final scalar type is the character, but it isn't often seen.
Expand All @@ -261,16 +262,22 @@ instead.

---

# Strings
# `String`s
```rust
// Owned, heap-allocated string *slice*
let s1: String = String::new("Hello, 🌍!");

let s1 = String::new("Hello, 🌍!");
// ^^^^^^ Owned, heap-allocated string
```

- Rust strings are UTF-8-encoded
- Rust `String`s are UTF-8-encoded
- Unlike C/C++: *Not null-terminated*
- Cannot be indexed like C strings
- `String` is heap-allocated
- Actually many types of strings in Rust
- `CString`
- `PathBuf`
- `OsString`
- ...

<!--
- Rusts strings are complicated, because all strings are complicated
Expand All @@ -294,7 +301,7 @@ fn main() {
- Group multiple values into a single compound type
- Fixed size
- Different types per element
- Create a tuple by writing a comma-separated list of values inside parentheses
- Create by writing a comma-separated list of values inside parentheses

::right::

Expand Down Expand Up @@ -406,9 +413,9 @@ fn also_returns_nothing() {
```

- The function boundary must always be explicitly annotated with types
- Within the function body type inference may be used
- Type inference may be used in function body
- A function that returns nothing has the return type *unit* (`()`)
- The function body contains a series of statements optionally ending with an
- Function body contains a series of statements optionally ending with an
expression

<!--
Expand Down Expand Up @@ -440,6 +447,10 @@ fn my_fun() {
let x = 10;
```

```rust
return 42;
```

<v-click>

```rust
Expand All @@ -465,9 +476,9 @@ statements

- Expressions evaluate to a resulting value
- Expressions make up most of the Rust code you write
- Includes all control flow such as `if` and `while`
- Includes all control flow such as `if` and `loop`
- Includes scoping braces (`{` and `}`)
- An expression can be turned into a statement by adding a semicolon (`;`)
- Semicolon (`;`) turns expression into statement

```rust {all|2-5}
fn main() {
Expand Down
10 changes: 9 additions & 1 deletion slides/A-foundations/closures.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
layout: default
---
# Intermezzo: Closures
# Closures

- Closures are anonymous (unnamed) functions
- they can capture ("close over") values in their scope
Expand All @@ -28,3 +28,11 @@ fn bar() -> i64 {
let evens: Vec<_> = some_iterator.filter(|x| x % 2 == 0).collect();
```

---

# To do

Content about
- `Fn`, `FnMut`, `FnOnce`, `fn`
- Closures as function parameters
- Closures in structs
16 changes: 7 additions & 9 deletions slides/A-foundations/composite-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,23 +144,21 @@ fn main() {
}
```

* Note: an enum always is as large as the largest variant
* An enum always is as large as the largest variant + tag

<!--<div class="relative">-->

<div style="margin-left:auto; margin-right:auto; display:block; width:50%;">
<div style="margin-left:auto; margin-right:auto; display:block; width:100%;">

<LightOrDark>
<template #dark>
<center>
<div style="padding: 20px; background-color:#1b1b1b; border-radius: var(--slidev-code-radius) !important;">
<img src="/images/A2-enum-memory-dark.svg"/>
</center>
</div>
</template>
<template #light>
<img src="/images/A2-enum-memory-light.svg"/>
<div style="padding: 20px; background-color:#F8F8F8; border-radius: var(--slidev-code-radius) !important;">
<img src="/images/A2-enum-memory-light.svg"/>
</div>
</template>
</LightOrDark>

</div>

<!--</div>-->
4 changes: 2 additions & 2 deletions slides/A-foundations/entry.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ theme: default
class: text-center
highlighter: shiki
lineNumbers: true
info: "Rust - A1: Language basics"
info: "Rust - A: Foundation"
drawings:
persist: false
fonts:
mono: Fira Mono
layout: cover
title: "Rust - A1: Language basics"
title: "Rust - A: Foundation"
---

# Rust programming
Expand Down
1 change: 1 addition & 0 deletions slides/A-foundations/images
27 changes: 14 additions & 13 deletions slides/A-foundations/impl-blocks.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@

---

# Intermission: Impl blocks
In the past few slides we saw a syntax which wasn't explained before:
# `impl` blocks
To associate functions to `structs` and `enums`, we use `impl` blocks

```rust {3}
fn main() {
Expand All @@ -17,7 +18,7 @@ fn main() {

---

# Intermission: Impl blocks
# `impl` blocks

```rust {all|6,13|7-12|7|17}
enum IpAddress {
Expand Down Expand Up @@ -50,7 +51,7 @@ fn main() {

---

# Intermission: Impl blocks, self and Self
# `self` and `Self`

- The `self` parameter defines how the method can be used.
- The `Self` type is a shorthand for the type on which the current
Expand All @@ -60,35 +61,35 @@ fn main() {
struct Foo(i32);

impl Foo {
fn consume(self) -> Self {
fn consume(self) -> Self { // Takes `Foo` by value, returns `Foo`
Self(self.0 + 1)
}

fn borrow(&self) -> &i32 {
fn borrow(&self) -> &i32 { // Takes immutable reference of `Foo`
&self.0
}

fn borrow_mut(&mut self) -> &mut i32 {
fn borrow_mut(&mut self) -> &mut i32 { // Takes mutable reference of `Foo`
&mut self.0
}

fn new() -> Self {
fn new() -> Self { // Associated function, returns `Foo`
Self(0)
}
}
```

---

# Intermission: Impl blocks, the self parameter
# `impl` blocks, the `self` parameter
The self parameter is called the *receiver*.

* The self parameter is always the first and it always has the type on which it
* The `self` parameter is always the first and it always has the type on which it
was defined
* We never specify the type of the self parameter
* We can optionally prepend `&` or `&mut ` to self to indicate that we take
* We never specify the type of the `self` parameter
* We can optionally prepend `&` or `&mut ` to `self` to indicate that we take
a value by reference
* Absence of a self parameter means that the function is an associated function
* Absence of a `self` parameter means that the function is an associated function
instead

```rust
Expand Down
8 changes: 8 additions & 0 deletions slides/A-foundations/interior-mutability.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

---

# To do:

Add content on interior mutability
- `Cell`
- `RefCell`
8 changes: 1 addition & 7 deletions slides/A-foundations/move-semantics.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@ we need them somewhere else

</Transform>


---
layout: section
---
# Rust's ownership model

---
layout: default
---
Expand Down Expand Up @@ -86,7 +80,7 @@ pointer (to the current stack frame) is decreased.
There are two mechanisms at play here, generally known as the stack and the heap

<div class="grid grid-cols-2">
<div class="flex flex-col rounded-md p-1 bg-teal-100 text-center w-md h-250px">
<div class="flex flex-col rounded-md p-1 bg-teal-100 text-center w-md h-300px">
<div class="bg-red-100 rounded-t-md flex flex-col">
<div class="bg-red-200 rounded-t-md p-1 border-red-500 border">Frame 1</div>
<div class="bg-red-200 p-1 border-red-500 border border-t-0">Frame 2</div>
Expand Down
39 changes: 39 additions & 0 deletions slides/A-foundations/optionals-errors.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@

---

# Generics
Structs become even more powerful if we introduce a little of generics

```rust
struct PointFloat(f64, f64);
struct PointInt(i64, i64);
```

We are repeating ourselves here, what if we could write a data structure for
both of these cases?

<v-click>

```rust
struct Point<T>(T, T);

fn main() {
let float_point: Point<f64> = Point(10.0, 10.0);
let int_point: Point<i64> = Point(10, 10);
}
```

Generics are much more powerful, but this is all we need for now

</v-click>

<!--
* The upper case letter between the angled brackets introduces a generic type
parameter.
* We can now use that generic type variable we introduced as a type name
* Then at the point of using the type we can specify which actual type we
want to use
* Generics are much more powerful, but this is enough for now
-->


---

# Option
Expand Down
10 changes: 5 additions & 5 deletions slides/A-foundations/ownership-borrowing.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,13 @@ hello, world

# Rules for borrowing and references

- You may only ever have one mutable reference at the same time
- You may have any number of immutable references at the same time as long as
there is no mutable reference
- You may only ever have **one mutable reference** at the same time
- You may have **any number of immutable references** at the same time **as long as
there is no mutable reference**
- References cannot *live* longer than their owners
- A reference will always at all times point to a valid value
- A reference will always at all times *point to a valid value*

These rules are enforced by the Rust compiler.
These rules are enforced by Rust's borrow checker.

<!--
- Rust tries to be smart about enforcing these rules, such that you don't notice
Expand Down
Loading

0 comments on commit c74bb90

Please sign in to comment.