Merge branch 'master' into master

This commit is contained in:
Sunface 2022-12-07 08:49:30 +08:00 committed by GitHub
commit 6883c069a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 89 additions and 43 deletions

View File

@ -15,7 +15,7 @@ fn main() {
}
```
A slice reference is a two-word object, for simplicity reasons, from now on we will use slice instead of `slice reference`. The first word is a pointer to the data, and the second word is the length of the slice. The word size is the same as usize, determined by the processor architecture, eg 64 bits on an x86-64. Slices can be used to borrow a section of an array, and have the type signature `&[T]`.
A slice reference is a two-word object, for simplicity reasons, from now on we will use slice instead of `slice reference`. The first word is a pointer to the data, and the second word is the length of the slice. The word size is the same as usize, determined by the processor architecture, e.g. 64 bits on an x86-64. Slices can be used to borrow a section of an array, and have the type signature `&[T]`.
2. 🌟🌟🌟
```rust,editable
@ -26,7 +26,7 @@ fn main() {
let slice = &arr[..2];
// Modify '8' to make it work
// TIPS: slice( reference ) IS NOT an array, if it is an array, then `assert!` will passed: Each of the two chars '中' and '国' occupies 4 bytes, 2 * 4 = 8
// TIPS: slice( reference ) IS NOT an array, if it is an array, then `assert!` will be passed: Each of the two chars '中' and '国' occupies 4 bytes, 2 * 4 = 8
assert!(std::mem::size_of_val(&slice) == 8);
println!("Success!");
@ -85,7 +85,7 @@ fn main() {
let mut s = String::from("hello world");
// Here, &s is `&String` type, but `first_word` need a `&str` type.
// It works because `&String` can be implicitly converted to `&str, If you want know more ,this is called `Deref`
// It works because `&String` can be implicitly converted to `&str. If you want know more, this is called `Deref coercion`.
let word = first_word(&s);
s.clear(); // error!
@ -97,4 +97,4 @@ fn first_word(s: &str) -> &str {
}
```
> You can find the solutions [here](https://github.com/sunface/rust-by-practice)(under the solutions path), but only use it when you need it
> You can find the solutions [here](https://github.com/sunface/rust-by-practice)(under the solutions path), but only use it when you need it

View File

@ -54,7 +54,7 @@ fn main() {
// Fix all errors without adding newline
fn main() {
let s = String::from("hello");
let s = String::from("hello");
s.push(',');
s.push(" world");
s += "!".to_string();
@ -89,13 +89,13 @@ fn main() {
let s1 = String::from("hello,");
let s2 = String::from("world!");
let s3 = s1 + s2;
assert_eq!(s3,"hello,world!");
println!("{}",s1);
assert_eq!(s3, "hello,world!");
println!("{}", s1);
}
```
### &str and String
Opsite to the seldom using of `str`, `&str` and `String` are used everywhere!
Opposite to the seldom using of `str`, `&str` and `String` are used everywhere!
7. 🌟🌟 `&str` can be converted to `String` in two ways
```rust,editable
@ -107,7 +107,7 @@ fn main() {
}
fn greetings(s: String) {
println!("{}",s)
println!("{}", s)
}
```
@ -140,7 +140,7 @@ fn main() {
println!("Unicode character {} (U+211D) is called {}",
unicode_codepoint, character_name );
let long_string = "String literals
let long_string = "String literals
can span multiple lines.
The linebreak and indentation here \
can be escaped too!";
@ -155,6 +155,7 @@ fn main() {
/* Fill in the blank and fix the errors */
fn main() {
let raw_str = r"Escapes don't work here: \x3F \u{211D}";
// Modify above line to make it work
assert_eq!(raw_str, "Escapes don't work here: ? ");
// If you need quotes in a raw string, add a pair of #s
@ -163,9 +164,10 @@ fn main() {
// If you need "# in your string, just use more #s in the delimiter.
// You can use up to 65535 #s.
let delimiter = r###"A string with "# in it. And even "##!"###;
let delimiter = r###"A string with "# in it. And even "##!"###;
println!("{}", delimiter);
// Fill the blank
let long_delimiter = __;
assert_eq!(long_delimiter, "Hello, \"##\"");
@ -262,4 +264,4 @@ fn main() {
}
```
> You can find the solutions [here](https://github.com/sunface/rust-by-practice)(under the solutions path), but only use it when you need it
> You can find the solutions [here](https://github.com/sunface/rust-by-practice)(under the solutions path), but only use it when you need it

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,15 @@ 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. 🌟
```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 +62,9 @@ fn main() {
}
```
2. 🌟🌟
```rust,editable
/* Make it work
- Dont use `_reborrow` and `_count_reborrowed`
@ -89,7 +93,9 @@ fn main() {
}
```
3. 🌟🌟
```rust,editable
/* Make it work in two ways, none of them is to remove `take(movable)` away from the code
*/
@ -132,14 +138,16 @@ let add_one_v3 = |x| { x + 1 };
let add_one_v4 = |x| x + 1 ;
```
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 +159,11 @@ 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. 🌟🌟
```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,
@ -198,7 +208,9 @@ 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. 🌟🌟
```rust,editable
/* Fill in the blank */
@ -254,7 +266,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 +297,9 @@ fn exec<F: Fn()>(f: F) {
}
```
8. 🌟🌟
```rust,editable
/* Fill in the blank */
fn main() {
@ -303,9 +317,11 @@ 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. 🌟🌟
```rust,editable
/* Implement `call_me` to make it work */
@ -326,16 +342,18 @@ 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. 🌟🌟
```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 +365,9 @@ fn main() {
}
```
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,13 +23,15 @@ fn main() {
}
```
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]);
}
}
```
@ -55,13 +57,15 @@ 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. 🌟🌟
```rust,editable
/* Fill the blanks and fix the errors.
Using two ways if possible */
@ -75,28 +79,32 @@ 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. 🌟
```rust,editable
/* Make it work */
fn main() {
let arr = vec![0; 10];
for i in arr {
println!("{}", i)
println!("{}", i);
}
println!("{:?}",arr);
}
```
5. 🌟
```rust,editable
/* Fill in the blank */
fn main() {
@ -113,7 +121,9 @@ fn main() {
}
```
6. 🌟🌟
```rust,editable
/* Fill in the blank */
fn main() {
@ -130,7 +140,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 +179,9 @@ fn main() {
}
```
7. 🌟🌟🌟
```rust,editable
struct Fibonacci {
curr: u32,
@ -208,8 +220,11 @@ 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
/* Fill in the blank and fix the errors */
fn main() {
let v1 = vec![1, 2, 3];
@ -226,10 +241,12 @@ 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. 🌟🌟
```rust,editable
/* Make it work */
use std::collections::HashMap;
@ -251,9 +268,11 @@ 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. 🌟🌟
```rust,editable
/* Fill in the blanks */
fn main() {
@ -265,7 +284,9 @@ fn main() {
}
```
11. 🌟🌟
```rust
/* Fill in the blanks */
use std::collections::HashMap;
@ -281,7 +302,9 @@ fn main() {
#### Using closures in iterator adaptors
12. 🌟🌟
```rust
/* Fill in the blanks */
#[derive(PartialEq, Debug)]

View File

@ -19,7 +19,7 @@ fn main() {
// Fill the blanks in the code to make it compile
fn main() {
let __ = 1;
let __ __ = 1;
__ += 2;
assert_eq!(x, 3);

View File

@ -155,7 +155,7 @@ fn main() {
```rust
fn main() {
let raw_str = "Escapes don't work here: \x3F \u{211D}";
// modify below line to make it work
// modify above line to make it work
assert_eq!(raw_str, "Escapes don't work here: ? ");
// If you need quotes in a raw string, add a pair of #s
@ -167,7 +167,7 @@ fn main() {
let delimiter = r###"A string with "# in it. And even "##!"###;
println!("{}", delimiter);
// fill the blank
// Fill the blank
let long_delimiter = r###"Hello, "##""###;
assert_eq!(long_delimiter, "Hello, \"##\"")
}

View File

@ -149,6 +149,7 @@ fn main() {
/* 填空并修复所有错误 */
fn main() {
let raw_str = r"Escapes don't work here: \x3F \u{211D}";
// 修改上面的行让代码工作
assert_eq!(raw_str, "Escapes don't work here: ? ");
// 如果你希望在字符串中使用双引号,可以使用以下形式
@ -254,4 +255,4 @@ fn main() {
```
> 你可以在[这里](https://github.com/sunface/rust-by-practice/blob/master/solutions/compound-types/string.md)找到答案(在 solutions 路径下)
> 你可以在[这里](https://github.com/sunface/rust-by-practice/blob/master/solutions/compound-types/string.md)找到答案(在 solutions 路径下)

View File

@ -68,7 +68,7 @@ Rust 的借用检查器使用显式的生命周期标注来确定一个引用的
**大家先忽略生命周期消除规则**,让我们看看,函数签名中的生命周期有哪些限制:
- 需要为每个引用标注上合适的生命周期
- 返回值中的引用,它的生命周期要么跟某个引用参数相同,要么是 `'statc`
- 返回值中的引用,它的生命周期要么跟某个引用参数相同,要么是 `'static`
**示例**
```rust,editable
@ -334,4 +334,4 @@ enum Either<'a> {
}
fn main() {}
```
```

View File

@ -24,11 +24,11 @@
我们使用 [mdbook](https://rust-lang.github.io/mdBook/) 构建在线练习题,你也可以下载到本地运行:
```shell
$ cargo install mdbook
$ cd rust-by-practice && mdbook serve
$ cd rust-by-practice && mdbook serve zh-CN/
```
在本地win 10或者linux服务器上运行时应当使用 -n 参数指定mdbook服务所监听的IP地址-p 参数指定服务监听的端口不指定则为默认的3000以win 10本地运行为例
```shell
$ mdbook serve -p 8888 -n 127.0.0.1
$ mdbook serve -p 8888 -n 127.0.0.1 zh-CN/
```
## 特性