mirror of
https://github.com/mainmatter/100-exercises-to-learn-rust
synced 2024-12-25 21:58:26 +01:00
Formatter
This commit is contained in:
parent
1aae615bb4
commit
4401743807
36 changed files with 0 additions and 36 deletions
|
@ -113,4 +113,3 @@ You can think of a type as a **tag** that the compiler attaches to every value i
|
|||
tag, the compiler can enforce different rules—e.g. you can't add a string to a number, but you can add two numbers
|
||||
together.
|
||||
If leveraged correctly, types can prevent whole classes of runtime bugs.
|
||||
|
||||
|
|
|
@ -14,4 +14,3 @@ It might not sound like much, but it'll give us a chance to cover a lot of Rust'
|
|||
Nailing the basics with a few exercises will get the language flowing under your fingers.
|
||||
When we move on to more complex topics, such as traits and ownership, you'll be able to focus on the new concepts
|
||||
without getting bogged down by the syntax or other trivial details.
|
||||
|
||||
|
|
|
@ -99,4 +99,3 @@ let message = if number < 5 {
|
|||
In the example above, each branch of the `if` evaluates to a string literal,
|
||||
which is then assigned to the `message` variable.\
|
||||
The only requirement is that both `if` branches return the same type.
|
||||
|
||||
|
|
|
@ -9,4 +9,3 @@ So far you've learned:
|
|||
- How to execute conditional logic via comparisons and `if`/`else` expressions
|
||||
|
||||
It looks like you're ready to tackle factorials!
|
||||
|
||||
|
|
|
@ -16,4 +16,3 @@ To move forward you'll have to pick up several new Rust concepts, such as:
|
|||
- Memory management: stack, heap, pointers, data layout, destructors
|
||||
- Modules and visibility
|
||||
- Strings
|
||||
|
||||
|
|
|
@ -136,4 +136,3 @@ let is_open = Ticket::is_open(ticket);
|
|||
|
||||
The function call syntax makes it quite clear that `ticket` is being used as `self`, the first parameter of the method,
|
||||
but it's definitely more verbose. Prefer the method call syntax when possible.
|
||||
|
||||
|
|
|
@ -112,4 +112,3 @@ where each name comes from and potentially introducing name conflicts.\
|
|||
Nonetheless, it can be useful in some cases, like when writing unit tests. You might have noticed
|
||||
that most of our test modules start with a `use super::*;` statement to bring all the items from the parent module
|
||||
(the one being tested) into scope.
|
||||
|
||||
|
|
|
@ -43,4 +43,3 @@ pub struct Configuration {
|
|||
|
||||
`Configuration` is public, but you can only access the `version` field from within the same crate.
|
||||
The `active` field, instead, is private and can only be accessed from within the same module or one of its submodules.
|
||||
|
||||
|
|
|
@ -106,4 +106,3 @@ ticket.set_title("New title".into());
|
|||
ticket.set_description("New description".into());
|
||||
ticket.set_status("In Progress".into());
|
||||
```
|
||||
|
||||
|
|
|
@ -3,4 +3,3 @@
|
|||
We've covered a lot of foundational Rust concepts in this chapter.\
|
||||
Before moving on, let's go through one last exercise to consolidate what we've learned.
|
||||
You'll have minimal guidance this time—just the exercise description and the tests to guide you.
|
||||
|
||||
|
|
|
@ -18,4 +18,3 @@ On top of traits as a concept, we'll also cover some of the key traits that are
|
|||
|
||||
Since we'll be talking about conversions, we'll seize the opportunity to plug some of the "knowledge gaps"
|
||||
from the previous chapter—e.g. what is `"A title"`, exactly? Time to learn more about slices too!
|
||||
|
||||
|
|
|
@ -96,4 +96,3 @@ impl PartialEq for MyType {
|
|||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -170,4 +170,3 @@ The rationale is the same as for [explicit type annotations on function paramete
|
|||
each function signature is a contract between the caller and the callee, and the terms must be explicitly stated.
|
||||
This allows for better error messages, better documentation, less unintentional breakages across versions,
|
||||
and faster compilation times.
|
||||
|
||||
|
|
|
@ -114,4 +114,3 @@ If a method returns a `&String`, you're promising that there is heap-allocated U
|
|||
**matches exactly** the one you're returning a reference to.\
|
||||
If a method returns a `&str`, instead, you have a lot more freedom: you're just saying that _somewhere_ there's a
|
||||
bunch of text data and that a subset of it matches what you need, therefore you're returning a reference to it.
|
||||
|
||||
|
|
|
@ -89,4 +89,3 @@ Automatically converting types can make the code harder to read and understand.
|
|||
is defined on both `T` and `U`, which one will be called?
|
||||
|
||||
We'll examine later in the course the "safest" use cases for deref coercion: smart pointers.
|
||||
|
||||
|
|
|
@ -77,4 +77,3 @@ All the types we've seen so far are `Sized`: `u32`, `String`, `bool`, etc.
|
|||
`str`, as we just saw, is not `Sized`.\
|
||||
`&str` is `Sized` though! We know its size at compile time: two `usize`s, one for the pointer
|
||||
and one for the length.
|
||||
|
||||
|
|
|
@ -138,4 +138,3 @@ In most cases, the target type is either:
|
|||
- Specified in the variable declaration with a type annotation (e.g. `let title: String = "A title".into();`)
|
||||
|
||||
`.into()` will work out of the box as long as the compiler can infer the target type from the context without ambiguity.
|
||||
|
||||
|
|
|
@ -105,4 +105,3 @@ struct MyType {
|
|||
The compiler implements `Clone` for `MyType` as you would expect: it clones each field of `MyType` individually and
|
||||
then constructs a new `MyType` instance using the cloned fields.\
|
||||
Remember that you can use `cargo expand` (or your IDE) to explore the code generated by `derive` macros.
|
||||
|
||||
|
|
|
@ -111,4 +111,3 @@ struct MyStruct {
|
|||
field: u32,
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -50,4 +50,3 @@ error[E0184]: the trait `Copy` cannot be implemented for this type; the type has
|
|||
2 | #[derive(Clone, Copy)]
|
||||
| ^^^^ `Copy` not allowed on types with destructors
|
||||
```
|
||||
|
||||
|
|
|
@ -25,4 +25,3 @@ A few guidelines to keep in mind:
|
|||
|
||||
Before moving on, let's go through one last exercise to consolidate what we've learned.
|
||||
You'll have minimal guidance this time—just the exercise description and the tests to guide you.
|
||||
|
||||
|
|
|
@ -13,4 +13,3 @@ We'll need to introduce a few more concepts along the way:
|
|||
- The `Error` trait, to mark error types
|
||||
- The `TryFrom` and `TryInto` traits, for fallible conversions
|
||||
- Rust's package system, explaining what's a library, what's a binary, how to use third-party crates
|
||||
|
||||
|
|
|
@ -41,4 +41,3 @@ enum Status {
|
|||
```
|
||||
|
||||
`enum`, just like `struct`, defines **a new Rust type**.
|
||||
|
||||
|
|
|
@ -68,4 +68,3 @@ match status {
|
|||
```
|
||||
|
||||
The `_` pattern matches anything that wasn't matched by the previous patterns.
|
||||
|
||||
|
|
|
@ -86,4 +86,3 @@ match status {
|
|||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -64,4 +64,3 @@ as the code that precedes it.
|
|||
Both `if let` and `let/else` are idiomatic Rust constructs.\
|
||||
Use them as you see fit to improve the readability of your code,
|
||||
but don't overdo it: `match` is always there when you need it.
|
||||
|
||||
|
|
|
@ -72,4 +72,3 @@ assert_eq!(second.2, 8);
|
|||
```
|
||||
|
||||
Tuples are a convenient way of grouping values together when you can't be bothered to define a dedicated struct type.
|
||||
|
||||
|
|
|
@ -81,4 +81,3 @@ That's the big advantage of `Result`: it makes fallibility explicit.
|
|||
|
||||
Keep in mind, though, that panics exist. They aren't tracked by the type system, just like exceptions in other languages.
|
||||
But they're meant for **unrecoverable errors** and should be used sparingly.
|
||||
|
||||
|
|
|
@ -38,4 +38,3 @@ When you call a function that returns a `Result`, you have two key options:
|
|||
Err(err) => eprintln!("Error: {}", err),
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -36,4 +36,3 @@ match s.parse_u32() {
|
|||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -50,4 +50,3 @@ The difference is in their _purpose_: `Display` returns a representation that's
|
|||
while `Debug` provides a low-level representation that's more suitable to developers and service operators.\
|
||||
That's why `Debug` can be automatically implemented using the `#[derive(Debug)]` attribute, while `Display`
|
||||
**requires** a manual implementation.
|
||||
|
||||
|
|
|
@ -61,4 +61,3 @@ binary crate inside. If you want to create a library crate instead, you can use
|
|||
```bash
|
||||
cargo new my-library --lib
|
||||
```
|
||||
|
||||
|
|
|
@ -52,4 +52,3 @@ static_assertions = "1.1.0"
|
|||
```
|
||||
|
||||
We've been using a few of these throughout the book to shorten our tests.
|
||||
|
||||
|
|
|
@ -39,4 +39,3 @@ In the case of `thiserror`, we have:
|
|||
- `#[derive(thiserror::Error)]`: this is the syntax to derive the `Error` trait for a custom error type, helped by `thiserror`.
|
||||
- `#[error("{0}")]`: this is the syntax to define a `Display` implementation for each variant of the custom error type.
|
||||
`{0}` is replaced by the zero-th field of the variant (`String`, in this case) when the error is displayed.
|
||||
|
||||
|
|
|
@ -38,4 +38,3 @@ being attempted.
|
|||
|
||||
Just like `From` and `Into`, `TryFrom` and `TryInto` are dual traits.\
|
||||
If you implement `TryFrom` for a type, you get `TryInto` for free.
|
||||
|
||||
|
|
|
@ -148,4 +148,3 @@ fn read_file() -> Result<String, std::io::Error> {
|
|||
You can use the `?` operator to shorten your error handling code significantly.\
|
||||
In particular, the `?` operator will automatically convert the error type of the fallible operation into the error type
|
||||
of the function, if a conversion is possible (i.e. if there is a suitable `From` implementation)
|
||||
|
||||
|
|
Loading…
Reference in a new issue