Merge pull request #336 from Tanish-Eagle/functional-editing

Functional editing
This commit is contained in:
Sunface 2022-12-07 08:39:11 +08:00 committed by GitHub
commit 575790d83a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 47 deletions

View File

@ -1,5 +1,5 @@
# Closure
Closures can capture the enclosing evironments. For example we can capture the `x` variable :
Closures can capture the enclosing environments. For example we can capture the `x` variable :
```rust
fn main() {
let x = 1;
@ -37,13 +37,13 @@ fn main() {
## Capturing
Closures can capture variables by borrowing or moving. But they prefer to capture by borrowing and only go lower when required:
- by reference: `&T`
- by mutable reference: `&mut T`
- by value: `T`
- By reference: `&T`
- By mutable reference: `&mut T`
- By value: `T`
1γ€πŸŒŸ
1.🌟
```rust,editable
/* Make it work with least changing */
/* Make it work with least amount of changes*/
fn main() {
let color = String::from("green");
@ -60,7 +60,7 @@ fn main() {
}
```
2γ€πŸŒŸπŸŒŸ
2.🌟🌟
```rust,editable
/* Make it work
- Dont use `_reborrow` and `_count_reborrowed`
@ -89,7 +89,7 @@ fn main() {
}
```
3γ€πŸŒŸπŸŒŸ
3.🌟🌟
```rust,editable
/* Make it work in two ways, none of them is to remove `take(movable)` away from the code
*/
@ -132,14 +132,14 @@ let add_one_v3 = |x| { x + 1 };
let add_one_v4 = |x| x + 1 ;
```
4γ€πŸŒŸ
4.🌟
```rust,editable
fn main() {
let example_closure = |x| x;
let s = example_closure(String::from("hello"));
/* Make it work, only changeg the following line */
/* Make it work, only change the following line */
let n = example_closure(5);
}
```
@ -151,9 +151,9 @@ When taking a closure as an input parameter, the closure's complete type must be
- FnMut: the closure uses the captured value by mutable reference (&mut T)
- FnOnce: the closure uses the captured value by value (T)
5γ€πŸŒŸπŸŒŸ
5.🌟🌟
```rust,editable
/* Make it work by change the trait bound, in two ways*/
/* Make it work by changing the trait bound, in two ways*/
fn fn_once<F>(func: F)
where
F: FnOnce(usize) -> bool,
@ -168,7 +168,7 @@ fn main() {
}
```
6、 🌟🌟
6. 🌟🌟
```rust,editable
fn main() {
let mut s = String::new();
@ -198,7 +198,7 @@ Which trait to use is determined by what the closure does with captured value.
This is because if a move is possible, then any type of borrow should also be possible. Note that the reverse is not true. If the parameter is annotated as `Fn`, then capturing variables by `&mut T` or `T` are not allowed.
7γ€πŸŒŸπŸŒŸ
7.🌟🌟
```rust,editable
/* Fill in the blank */
@ -254,7 +254,7 @@ fn main() {
}
```
move closures may still implement `Fn` or `FnMut`, even though they capture variables by move. This is because the traits implemented by a closure type are determined by what the closure does with captured values, not how it captures them. The `move` keyword only specifies the latter.
Move closures may still implement `Fn` or `FnMut`, even though they capture variables by move. This is because the traits implemented by a closure type are determined by what the closure does with captured values, not how it captures them. The `move` keyword only specifies the latter.
```rust
fn main() {
@ -285,7 +285,7 @@ fn exec<F: Fn()>(f: F) {
}
```
8γ€πŸŒŸπŸŒŸ
8.🌟🌟
```rust,editable
/* Fill in the blank */
fn main() {
@ -303,9 +303,9 @@ fn exec<'a, F: __>(mut f: F) {
## Input functions
Since closure maybe used as arguments, you might wonder can we use functions as arguments too? And indeed they can.
Since closure can be used as arguments, you might wonder can we use functions as arguments too? And indeed we can.
9γ€πŸŒŸπŸŒŸ
9.🌟🌟
```rust,editable
/* Implement `call_me` to make it work */
@ -326,16 +326,16 @@ fn main() {
```
## Closure as return types
Returning a closure is much harder than you may thought of.
Returning a closure is much harder than you may have thought of.
10γ€πŸŒŸπŸŒŸ
10.🌟🌟
```rust,editable
/* Fill in the blank using two approches,
/* Fill in the blank using two aproaches,
and fix the errror */
fn create_fn() -> __ {
let num = 5;
// how does the following closure capture the evironment variable `num`
// How does the following closure capture the environment variable `num`
// &T, &mut T, T ?
|x| x + num
}
@ -347,7 +347,7 @@ fn main() {
}
```
11γ€πŸŒŸπŸŒŸ
11.🌟🌟
```rust,editable
/* Fill in the blank and fix the error*/
fn factory(x:i32) -> __ {

View File

@ -11,7 +11,7 @@ fn main() {
}
```
In above code, You may consider `for` as a simple loop, but actually it is iterating over a iterator.
In the code above, You may consider `for` as a simple loop, but actually it is iterating over a iterator.
By default `for` will apply the `into_iter` to the collection, and change it into a iterator. As a result, the following code is equivalent to previous one:
```rust
@ -23,18 +23,18 @@ fn main() {
}
```
1γ€πŸŒŸ
1.🌟
```rust,editable
/* Refactoring the following code using iterators */
fn main() {
let arr = [0; 10];
for i in 0..arr.len() {
println!("{}",arr[i])
println!("{}",arr[i]);
}
}
```
2、 🌟 One of the easiest ways to create an iterator is to use the range notion: `a..b`.
2. 🌟 One of the easiest ways to create an iterator is to use the range notion: `a..b`.
```rust,editable
/* Fill in the blank */
fn main() {
@ -55,13 +55,13 @@ pub trait Iterator {
fn next(&mut self) -> Option<Self::Item>;
// methods with default implementations elided
// Methods with default implementations elided
}
```
And we can call the `next` method on iterators directly.
3γ€πŸŒŸπŸŒŸ
3.🌟🌟
```rust,editable
/* Fill the blanks and fix the errors.
Using two ways if possible */
@ -75,28 +75,28 @@ fn main() {
```
## into_iter, iter and iter_mut
In the previous section, we have mentioned that `for` will apply the `into_iter` to the collection, and change it into a iterator.However, this is not the only way to convert collections into iterators.
In the previous section, we have mentioned that `for` will apply the `into_iter` to the collection, and change it into a iterator. However, this is not the only way to convert collections into iterators.
`into_iter`, `iter`, `iter_mut`, all of them can convert an collection into iterator, but in different ways.
`into_iter`, `iter`, `iter_mut`, all of them can convert a collection into iterator, but in different ways.
- `into_iter` cosumes the collection, once the collection has been comsumed, it is no longer available for reuse, because its ownership has been moved within the loop.
- `into_iter` consumes the collection, once the collection has been consumed, it is no longer available for reuse, because its ownership has been moved within the loop.
- `iter`, this borrows each element of the collection through each iteration, thus leaving the collection untouched and available for reuse after the loop
- `iter_mut`, this mutably borrows each element of the collection, allowing for the collection to be modified in place.
4γ€πŸŒŸ
4.🌟
```rust,editable
/* Make it work */
fn main() {
let arr = vec![0; 10];
for i in arr {
println!("{}", i)
println!("{}", i);
}
println!("{:?}",arr);
}
```
5γ€πŸŒŸ
5.🌟
```rust,editable
/* Fill in the blank */
fn main() {
@ -113,7 +113,7 @@ fn main() {
}
```
6γ€πŸŒŸπŸŒŸ
6.🌟🌟
```rust,editable
/* Fill in the blank */
fn main() {
@ -130,7 +130,7 @@ fn main() {
## Creating our own iterator
We can not only create iterators from collections types, but also can create iterators by implementing the `Iterator` trait on our own types.
We can not only create iterators from collection's types, but also can create iterators by implementing the `Iterator` trait on our own types.
**Example**
```rust
@ -169,7 +169,7 @@ fn main() {
}
```
7γ€πŸŒŸπŸŒŸπŸŒŸ
7.🌟🌟🌟
```rust,editable
struct Fibonacci {
curr: u32,
@ -208,8 +208,8 @@ The `Iterator` trait has a number of methods with default implementations provid
### Consuming adaptors
Some of these methods call the method `next`to use up the iterator, so they are called *consuming adaptors*.
8γ€πŸŒŸπŸŒŸ
```rust,edtiable
8.🌟🌟
```rust,editable
/* Fill in the blank and fix the errors */
fn main() {
let v1 = vec![1, 2, 3];
@ -226,10 +226,10 @@ fn main() {
```
#### collect
Other than converting a collection into an iterator, we can also `collect` the result values into a collection, `collect` will cosume the iterator.
#### Collect
Other than converting a collection into an iterator, we can also `collect` the result values into a collection, `collect` will consume the iterator.
9γ€πŸŒŸπŸŒŸ
9.🌟🌟
```rust,editable
/* Make it work */
use std::collections::HashMap;
@ -251,9 +251,9 @@ fn main() {
### Iterator adaptors
Methods allowing you to change one iterator into another iterator are known as *iterator adaptors*. You can chain multiple iterator adaptors to perform complex actions in a readable way.
But because **all iterators are lazy**, you have to call one of the consuming adapers to get results from calls to iterator adapters.
But because **all iterators are lazy**, you have to call one of the consuming adapters to get results from calls to iterator adapters.
10γ€πŸŒŸπŸŒŸ
10.🌟🌟
```rust,editable
/* Fill in the blanks */
fn main() {
@ -265,7 +265,7 @@ fn main() {
}
```
11γ€πŸŒŸπŸŒŸ
11.🌟🌟
```rust
/* Fill in the blanks */
use std::collections::HashMap;
@ -281,7 +281,7 @@ fn main() {
#### Using closures in iterator adaptors
12γ€πŸŒŸπŸŒŸ
12.🌟🌟
```rust
/* Fill in the blanks */
#[derive(PartialEq, Debug)]