mirror of
https://gitlab.com/djdietrick/docs
synced 2026-05-03 03:50:54 -04:00
Progress on rust advanced, left todos in rust index
This commit is contained in:
65
docs/rust/advanced/closures.md
Normal file
65
docs/rust/advanced/closures.md
Normal 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();
|
||||
```
|
||||
75
docs/rust/advanced/tests.md
Normal file
75
docs/rust/advanced/tests.md
Normal 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
|
||||
}
|
||||
```
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,2 +1,9 @@
|
||||
# Rust
|
||||
|
||||
## Todo
|
||||
|
||||
- Pointers
|
||||
- Macros
|
||||
- Iterators
|
||||
- Closures (finish)
|
||||
- Threads
|
||||
@@ -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"}
|
||||
]
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user