1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-07-11 16:50:16 +02:00

Introduce 'Idiomatic Rust' module

This commit is contained in:
LukeMathWalker
2025-07-01 15:56:39 +02:00
parent 010b443615
commit 1508dbb9f0
4 changed files with 130 additions and 0 deletions

View File

@ -429,6 +429,14 @@
--- ---
# Idiomatic Rust
- [Welcome](idiomatic/welcome.md)
- [Leveraging the Type System](idiomatic/leveraging-the-type-system.md)
- [Newtype Pattern](idiomatic/leveraging-the-type-system/newtype-pattern.md)
---
# Final Words # Final Words
- [Thanks!](thanks.md) - [Thanks!](thanks.md)

View File

@ -0,0 +1,47 @@
---
minutes: 5
---
# Leveraging the Type System
Rust's type system is _expressive_.\
We can use types and traits to build abstractions that make our code harder to
misuse. In some cases, we can even go as far as enforcing correctness at
_compile-time_. Quite often, these abstractions have no runtime
overhead[^zero-cost].
The type system can also be used to model concepts and constraints from your
business domain. By designing our types carefully, we can improve the clarity
and maintainability of the entire codebase.
<details>
Additional items speaker may mention:
- Rust's type system borrows a lot of ideas from functional programming
languages.\
For example, Rust's enums are known as "algebraic data types" in languages
like Haskell and OCaml. You can take inspiration from learning material geared
towards functional languages when looking for guidance on how to design with
types. ["Domain Modeling Made Functional"][1] is a great resource on the
topic, with examples written in F#.
- Despite its functional roots, functional design patterns don't translate as-is
to Rust. For instance, extensive use of higher-kinded functions and types can
result in code that is harder to read and maintain. Design patterns in Rust
must take into account (and leverage!) the granular control over mutability
that comes with its borrow-checker.
- The same caution should be applied to object-oriented design patterns. Rust
doesn't support inheritance, and object boundaries must be mindful of the
constraints introduced by the borrow-checker.
</details>
{{%segment outline}}
[1]: https://pragprog.com/titles/swdddf/domain-modeling-made-functional/
[^zero-cost]: They often referred to as "zero-cost abstractions", although the
label can be misleading: the impact on compile times and code complexity may
be significant.

View File

@ -0,0 +1,49 @@
---
minutes: 5
---
# Newtype Pattern
A _newtype_ is a wrapper around an existing type, often a primitive:
```rust
/// A unique user identifier, implemented as a newtype around `u64`.
pub struct UserId(u64);
```
Unlike type aliases, newtypes aren't interchangeable with the wrapped type:
```rust,compile_fail
# pub struct UserId(u64);
fn double(n: u64) -> u64 {
n * 2
}
// This doesn't compile ❌
double(UserId(1));
```
The Rust compiler won't implicitly convert to (or from) the underlying type.\
It won't let you use methods or operators defined on the underlying type either:
```rust,compile_fail
# pub struct UserId(u64);
// This doesn't compile ❌
assert_ne!(UserId(1), UserId(2));
```
<details>
- Run the example to show students the error message from the compiler.
- Modify the example to use a typealias instead of a newtype, such as
`type MessageId = u64`. The modified example should compile, thus highlighting
the differences between the two approaches.
- Stress that newtypes, out of the box, have no behaviour attached to them. You
need to be intentional about which methods and operators you are willing to
forward from the underlying type. In our `UserId` example, it is reasonable to
allow comparisons between `UserId`s, but it wouldn't make sense to allow
arithmetic operations like addition or subtraction.
</details>

26
src/idiomatic/welcome.md Normal file
View File

@ -0,0 +1,26 @@
---
course: Idiomatic Rust
session: Morning
target_minutes: 180
---
# Welcome to Idiomatic Rust
[Rust Fundamentals](../welcome-day-1.md) introduced Rust syntax and core
concepts. We now want to go one step further: how do you use Rust _effectively_
in your projects? What does _idiomatic_ Rust look like?
This course is opinionated: we will nudge you towards some patterns, and away
from others. Nonetheless, we do recognize that some projects may have different
needs. We always provide the necessary information to help you make informed
decisions within the context and constraints of your own projects.
> ⚠️ This course is under **active development**.
>
> The material may change frequently and there might be errors that have not yet
> been spotted. Nonetheless, we encourage you to browse through and provide
> early feedback!
## Schedule
{{%session outline}}