Progress on rust advanced, left todos in rust index

This commit is contained in:
2022-09-23 13:43:01 -04:00
parent 002d43b32c
commit 9afa78fb68
6 changed files with 158 additions and 2 deletions

View File

@@ -0,0 +1,65 @@
# Closures
Closures are anonymous functions that capture the scope in which they are defined. They can be saved as a variable or passed into a function.
```rust
struct HelloWorld {
msg: String
}
impl HelloWorld {
fn test_closure(&self, name: Option<&str>) -> String {
String::from(format!(self.msg, name.unwrap_or_else(|| self.default_name())))
}
fn default_name() -> String {
return String::from("David")
}
}
// Example with parameter and return value
let expensive_closure = |num: u32| -> u32 {
println!("calculating slowly...");
thread::sleep(Duration::from_secs(2));
num
};
```
## Ownership and References
### Immutable reference
```rust
let list = vec![1, 2, 3];
println!("Before defining closure: {:?}", list);
let only_borrows = || println!("From closure: {:?}", list);
println!("Before calling closure: {:?}", list);
only_borrows();
println!("After calling closure: {:?}", list);
```
### Mutable reference
```rust
let mut list = vec![1, 2, 3];
println!("Before defining closure: {:?}", list);
let mut borrows_mutably = || list.push(7);
borrows_mutably();
println!("After calling closure: {:?}", list);
```
### Take ownership with `move`
```rust
use std::thread;
let list = vec![1, 2, 3];
println!("Before defining closure: {:?}", list);
thread::spawn(move || println!("From thread: {:?}", list))
.join()
.unwrap();
```

View File

@@ -0,0 +1,75 @@
# Testing
Test functions are defined with the `#[test]` attribute. Within the tests, we use the `assert!` macro to evaluate a boolean and fail the tests if it does not pass. You can also use `assert_eq!` and `assert_ne!` to test equality directly, however the values being tested must implement `PartialEq` and `Debug` traits.
## Unit Tests
For unit tests, its best to write your tests in the file that it is testing but contain it with a `mod tests` with the `cfg(test)` attribute. This will exclude it from the final executable or library. Unit tests also allow you to test private functions, meaning ones that are not `pub`.
```rust
#[cfg(test)]
mod tests {
use super::*; // Use this to call functions in the current file
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
assert!(result == 4);
}
#[test]
fn greeting_contains_name() {
let result = greeting("Carol");
// Custom failure message
assert!(
result.contains("Carol"),
"Greeting did not contain name, value was `{}`",
result
);
}
// Will pass if test panics
#[test]
#[should_panic]
fn greater_than_100() {
// Something illegal
}
}
```
## Integration Tests
Integration tests live in a separate `tests` directory at the base of the project. These should test your library from a black box perspective, meaning you use it the same way a consumer would. You do not need to wrap integration tests with a `mod tests` and `#[cfg(tests)]` because they are automatically excluded from the build. To include files that provide common functionality to tests but are not tests themselves, you need to make them a module by creating a directory with a `mod.rs` (ex. `tests/common.mod.rs`).
```rust
use adder; // our lib
mod common;
#[test]
fn it_adds_two() {
common::setup();
assert_eq!(4, adder::add_two(2));
}
```
## Documentation Tests
You can define documentation comments with `///` which allows you to provide markdown that gets built into an HTML documentation. If you create code blocks, you can write valid rust code and even add assertions to create tests. These will run when you `cargo test`.
```rust
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let arg = 5;
/// let answer = my_crate::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
x + 1
}
```

View File

@@ -91,6 +91,8 @@ fn some_function<T, U>(t: &T, u: &U) -> i32
## Returning types that implement traits
You can only use a trait as a return value if you are returning a single type.
```rust
fn returns_summarizable() -> impl Summary {
Tweet {

View File

@@ -42,7 +42,12 @@ let greeting_file = match greeting_file_result {
```rust
let greeting_file = File::open("hello.txt").unwrap();
let greeting_file = File::open("hello.txt")e.expect("hello.txt should be included in this project");
let greeting_file = File::open("hello.txt").expect("hello.txt should be included in this project");
```
You can also use `unwrap_or_else` and pass a closure to return a value if something goes wrong.
```rust
let greeting_file = File::open("hello.txt").unwrap_or_else(|| None ) // return something else
```
### Propagate an error

View File

@@ -1,2 +1,9 @@
# Rust
## Todo
- Pointers
- Macros
- Iterators
- Closures (finish)
- Threads

View File

@@ -18,7 +18,9 @@
"text": "Advanced",
"items": [
{"text": "Generics", "link": "/rust/advanced/generics"},
{"text": "Traits", "link": "/rust/advanced/traits"}
{"text": "Traits", "link": "/rust/advanced/traits"},
{"text": "Tests", "link": "/rust/advanced/tests"},
{"text": "Closures", "link": "/rust/advanced/closures"}
]
}
]