Merge pull request #336 from Tanish-Eagle/functional-editing
Functional editing
This commit is contained in:
commit
575790d83a
|
@ -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) -> __ {
|
||||
|
|
|
@ -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)]
|
||||
|
|
Loadingβ¦
Reference in New Issue