Merge pull request #219 from Tanish-Eagle/editting-compound-types

Editting compound types
This commit is contained in:
Sunface 2022-04-22 09:00:24 +08:00 committed by GitHub
commit b5d490bbb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 125 additions and 125 deletions

View File

@ -1,26 +1,26 @@
# Array
The type of array is `[T; Lengh]`, as you can see, array's lengh is part of their type signature. So their length must be known at compile time.
The type of array is `[T; Length]`, as you can see, array's length is part of their type signature. So their length must be known at compile time.
For example, you cant initialized an array as below:
For example, you cant initialize an array like below:
```rust
fn init_arr(n: i32) {
let arr = [1; n];
}
```
This will cause an error, because the compile have no idea of the exact size of the array in compile time.
This will cause an error, because the compiler has no idea of the exact size of the array at compile time.
1. 🌟
```rust,editable
fn main() {
// fill the blank with proper array type
// Fill the blank with proper array type
let arr: __ = [1, 2, 3, 4, 5];
// modify below to make it work
// Modify the code below to make it work
assert!(arr.len() == 4);
println!("Success!")
println!("Success!");
}
```
@ -28,16 +28,16 @@ fn main() {
```rust,editable
fn main() {
// we can ignore parts of the array type or even the whole type, let the compiler infer it for us
// We can ignore parts of the array type or even the whole type, let the compiler infer it for us
let arr0 = [1, 2, 3];
let arr: [_; 3] = ['a', 'b', 'c'];
// fill the blank
// Arrays are stack allocated, `std::mem::size_of_val` return the bytes which array occupies
// A char takes 4 byte in Rust: Unicode char
// Fill the blank
// Arrays are stack allocated, `std::mem::size_of_val` returns the bytes which an array occupies
// A char takes 4 bytes in Rust: Unicode char
assert!(std::mem::size_of_val(&arr) == __);
println!("Success!")
println!("Success!");
}
```
@ -46,13 +46,13 @@ fn main() {
```rust,editable
fn main() {
// fill the blank
// Fill the blank
let list: [i32; 100] = __ ;
assert!(list[0] == 1);
assert!(list.len() == 100);
println!("Success!")
println!("Success!");
}
```
@ -60,10 +60,10 @@ fn main() {
```rust,editable
fn main() {
// fix the error
// Fix the error
let _arr = [1, 2, '3'];
println!("Success!")
println!("Success!");
}
```
@ -73,28 +73,28 @@ fn main() {
fn main() {
let arr = ['a', 'b', 'c'];
let ele = arr[1]; // only modify this line to make the code work!
let ele = arr[1]; // Only modify this line to make the code work!
assert!(ele == 'a');
println!("Success!")
println!("Success!");
}
```
6. 🌟 Out of bounds indexing causes `panic`.
```rust,editable
// fix the error
// Fix the error
fn main() {
let names = [String::from("Sunfei"), "Sunface".to_string()];
// `get` returns an Option<T>, it's safe to use
// `Get` returns an Option<T>, it's safe to use
let name0 = names.get(0).unwrap();
// but indexing is not safe
// But indexing is not safe
let _name1 = &names[2];
println!("Success!")
println!("Success!");
}
```

View File

@ -3,7 +3,7 @@
```rust,editable
// fix the errors
// Fix the errors
enum Number {
Zero,
One,
@ -25,18 +25,18 @@ enum Number2 {
fn main() {
// a enum variant can be converted to a integer by `as`
// An enum variant can be converted to a integer by `as`
assert_eq!(Number::One, Number1::One);
assert_eq!(Number1::One, Number2::One);
println!("Success!")
println!("Success!");
}
```
2. 🌟 each enum variant can hold its own data.
2. 🌟 Each enum variant can hold its own data.
```rust,editable
// fill in the blank
// Fill in the blank
enum Message {
Quit,
Move { x: i32, y: i32 },
@ -45,17 +45,17 @@ enum Message {
}
fn main() {
let msg1 = Message::Move{__}; // instantiating with x = 1, y = 2
let msg2 = Message::Write(__); // instantiating with "hello, world!"
let msg1 = Message::Move{__}; // Instantiating with x = 1, y = 2
let msg2 = Message::Write(__); // Instantiating with "hello, world!"
println!("Success!")
println!("Success!");
}
```
3. 🌟🌟 we can get the data which a enum variant is holding by pattern match
3. 🌟🌟 We can get the data which an enum variant is holding by pattern match.
```rust,editable
// fill in the blank and fix the error
// Fill in the blank and fix the error
enum Message {
Quit,
Move { x: i32, y: i32 },
@ -72,7 +72,7 @@ fn main() {
panic!("NEVER LET THIS RUN");
}
println!("Success!")
println!("Success!");
}
```
@ -80,7 +80,7 @@ fn main() {
```rust,editable
// fill in the blank and fix the errors
// Fill in the blank and fix the errors
enum Message {
Quit,
Move { x: i32, y: i32 },
@ -105,11 +105,11 @@ fn show_message(msg: Message) {
}
```
5. 🌟🌟 As there is no `null` in Rust, we have to use enum `Option<T>` to deal the cases when value is absent.
5. 🌟🌟 Since there is no `null` in Rust, we have to use enum `Option<T>` to deal with the cases when the value is absent.
```rust,editable
// fill in the blank to make the `println` work.
// also add some code to prevent the `panic` from running.
// Fill in the blank to make the `println` work.
// Also add some code to prevent the `panic` from running.
fn main() {
let five = Some(5);
let six = plus_one(five);
@ -118,7 +118,7 @@ fn main() {
if let __ = six {
println!("{}", n);
println!("Success!")
println!("Success!");
}
panic!("NEVER LET THIS RUN");
@ -133,7 +133,7 @@ fn plus_one(x: Option<i32>) -> Option<i32> {
```
6. 🌟🌟🌟🌟 implement a `linked-list` via enums.
6. 🌟🌟🌟🌟 Implement a `linked-list` via enums.
```rust,editable
@ -166,12 +166,12 @@ impl List {
// depends on the variant of `self`
// `self` has type `&List`, and `*self` has type `List`, matching on a
// concrete type `T` is preferred over a match on a reference `&T`
// after Rust 2018 you can use self here and tail (with no ref) below as well,
// After Rust 2018 you can use self here and tail (with no ref) below as well,
// rust will infer &s and ref tail.
// See https://doc.rust-lang.org/edition-guide/rust-2018/ownership-and-lifetimes/default-match-bindings.html
match *self {
// Can't take ownership of the tail, because `self` is borrowed;
// instead take a reference to the tail
// Instead take a reference to the tail
Cons(_, ref tail) => 1 + tail.len(),
// Base Case: An empty list has zero length
Nil => 0

View File

@ -4,18 +4,18 @@ Slices are similar to arrays, but their length is not known at compile time, so
1. 🌟🌟 Here, both `[i32]` and `str` are slice types, but directly using it will cause errors. You have to use the reference of the slice instead: `&[i32]`, `&str`.
```rust,editable
// fix the errors, DON'T add new lines!
// Fix the errors, DON'T add new lines!
fn main() {
let arr = [1, 2, 3];
let s1: [i32] = arr[0..2];
let s2: str = "hello, world" as str;
println!("Success!")
println!("Success!");
}
```
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, eg 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
@ -25,11 +25,11 @@ fn main() {
let slice = &arr[..2];
// modify '6' to make it work
// TIPS: slice( reference ) IS NOT an array, if it is an array, then `assert!` will passed: each of the two UTF-8 chars '中' and '国' occupies 3 bytes, 2 * 3 = 6
// Modify '6' to make it work
// TIPS: slice( reference ) IS NOT an array, if it is an array, then `assert!` will passed: Each of the two UTF-8 chars '中' and '国' occupies 3 bytes, 2 * 3 = 6
assert!(std::mem::size_of_val(&slice) == 6);
println!("Success!")
println!("Success!");
}
```
@ -38,15 +38,15 @@ fn main() {
fn main() {
let arr: [i32; 5] = [1, 2, 3, 4, 5];
// fill the blanks to make the code work
// Fill the blanks to make the code work
let slice: __ = __;
assert_eq!(slice, &[2, 3, 4]);
println!("Success!")
println!("Success!");
}
```
### string slices
### String slices
4. 🌟
```rust,editable
@ -54,12 +54,12 @@ fn main() {
let s = String::from("hello");
let slice1 = &s[0..2];
// fill the blank to make the code work, DON'T USE 0..2 again
// Fill the blank to make the code work, DON'T USE 0..2 again
let slice2 = &s[__];
assert_eq!(slice1, slice2);
println!("Success!")
println!("Success!");
}
```
@ -68,24 +68,24 @@ fn main() {
fn main() {
let s = "你好,世界";
// modify this line to make the code work
// Modify this line to make the code work
let slice = &s[0..2];
assert!(slice == "你");
println!("Success!")
println!("Success!");
}
```
6. 🌟🌟 `&String` can be implicitly converted into `&str`.
```rust,editable
// fix errors
// Fix errors
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`
// 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`
let word = first_word(&s);
s.clear(); // error!

View File

@ -1,17 +1,17 @@
# string
# String
The type of string literal `"hello, world"` is `&str`, e.g `let s: &str = "hello, world"`.
### str and &str
1. 🌟 We can't use `str` type in normal ways, but we can use `&str`
### Str and &str
1. 🌟 We can't use `str` type in normal ways, but we can use `&str`.
```rust,editable
// fix error without adding new line
// Fix error without adding new line
fn main() {
let s: str = "hello, world";
println!("Success!")
println!("Success!");
}
```
@ -20,7 +20,7 @@ fn main() {
```rust,editable
// fix the error with at least two solutions
// Fix the error with at least two solutions
fn main() {
let s: Box<str> = "hello, world".into();
greetings(s)
@ -37,7 +37,7 @@ fn greetings(s: &str) {
3. 🌟
```rust,editable
// fill the blank
// Fill the blank
fn main() {
let mut s = __;
s.push_str("hello, world");
@ -45,28 +45,28 @@ fn main() {
assert_eq!(s, "hello, world!");
println!("Success!")
println!("Success!");
}
```
4. 🌟🌟🌟
```rust,editable
// fix all errors without adding newline
// Fix all errors without adding newline
fn main() {
let s = String::from("hello");
s.push(',');
s.push(" world");
s += "!".to_string();
println!("{}", s)
println!("{}", s);
}
```
5. 🌟🌟 `replace` can be used to replace substring
```rust,editable
// fill the blank
// Fill the blank
fn main() {
let s = String::from("I like dogs");
// Allocate new memory and store the modified string there
@ -74,17 +74,17 @@ fn main() {
assert_eq!(s1, "I like cats");
println!("Success!")
println!("Success!");
}
```
More `String` methods can be found under [String](https://doc.rust-lang.org/std/string/struct.String.html) module.
6. 🌟🌟 You can only concat a `String` with `&str`, and `String`'s ownership can be moved to another variable
6. 🌟🌟 You can only concat a `String` with `&str`, and `String`'s ownership can be moved to another variable.
```rust,editable
// fix errors without removing any line
// Fix errors without removing any line
fn main() {
let s1 = String::from("hello,");
let s2 = String::from("world!");
@ -100,7 +100,7 @@ Opsite to the seldom using of `str`, `&str` and `String` are used everywhere!
7. 🌟🌟 `&str` can be converted to `String` in two ways
```rust,editable
// fix error with at lest two solutions
// Fix error with at least two solutions
fn main() {
let s = "hello, world";
greetings(s)
@ -115,25 +115,25 @@ fn greetings(s: String) {
```rust,editable
// use two approaches to fix the error and without adding a new line
// Use two approaches to fix the error and without adding a new line
fn main() {
let s = "hello, world".to_string();
let s1: &str = s;
println!("Success!")
println!("Success!");
}
```
### string escapes
### String escapes
9. 🌟
```rust,editable
fn main() {
// You can use escapes to write bytes by their hexadecimal values
// fill the blank below to show "I'm writing Rust"
// Fill the blank below to show "I'm writing Rust"
let byte_escape = "I'm writing Ru\x73__!";
println!("What are you doing\x3F (\\x3F means ?) {}", byte_escape);
// ...or Unicode code points.
// ...Or Unicode code points.
let unicode_codepoint = "\u{211D}";
let character_name = "\"DOUBLE-STRUCK CAPITAL R\"";
@ -169,11 +169,11 @@ fn main() {
let long_delimiter = __;
assert_eq!(long_delimiter, "Hello, \"##\"");
println!("Success!")
println!("Success!");
}
```
### byte string
### Byte string
Want a string that's not UTF-8? (Remember, str and String must be valid UTF-8). Or maybe you want an array of bytes that's mostly text? Byte strings to the rescue!
**Example**:
@ -189,8 +189,8 @@ fn main() {
// Byte strings can have byte escapes...
let escaped = b"\x52\x75\x73\x74 as bytes";
// ...but no unicode escapes
// let escaped = b"\u{211D} is not allowed";
// ...But no unicode escapes
// let escaped = b"\u{211D} Is not allowed";
println!("Some escaped bytes: {:?}", escaped);
@ -207,7 +207,7 @@ fn main() {
like with normal raw strings"#;
// Byte strings don't have to be UTF-8
let shift_jis = b"\x82\xe6\x82\xa8\x82\xb1\x82\xbb"; // "ようこそ" in SHIFT-JIS
let shift_jis = b"\x82\xe6\x82\xa8\x82\xb1\x82\xbb"; // "ようこそ" In SHIFT-JIS
// But then they can't always be converted to `str`
match str::from_utf8(shift_jis) {
@ -219,29 +219,29 @@ fn main() {
A more detailed listing of the ways to write string literals and escape characters is given in the ['Tokens' chapter](https://doc.rust-lang.org/reference/tokens.html) of the Rust Reference.
### string index
### String index
11. 🌟🌟🌟 You can't use index to access a char in a string, but you can use slice `&s1[start..end]`.
```rust,editable
fn main() {
let s1 = String::from("hi,中国");
let h = s1[0]; //modify this line to fix the error, tips: `h` only takes 1 byte in UTF8 format
let h = s1[0]; // Modify this line to fix the error, tips: `h` only takes 1 byte in UTF8 format
assert_eq!(h, "h");
let h1 = &s1[3..5];//modify this line to fix the error, tips: `中` takes 3 bytes in UTF8 format
let h1 = &s1[3..5]; // Modify this line to fix the error, tips: `中` takes 3 bytes in UTF8 format
assert_eq!(h1, "中");
println!("Success!")
println!("Success!");
}
```
### operate on UTF8 string
### Operate on UTF8 string
12. 🌟
```rust,editable
fn main() {
// fill the blank to print each char in "你好,世界"
// Fill the blank to print each char in "你好,世界"
for c in "你好,世界".__ {
println!("{}", c)
}

View File

@ -1,10 +1,10 @@
# Struct
### There types of structs
### The types of structs
1. 🌟 We must specify concrete values for each of the fields in struct.
```rust,editable
// fix the error
// Fix the error
struct Person {
name: String,
age: u8,
@ -17,7 +17,7 @@ fn main() {
age,
};
println!("Success!")
println!("Success!");
}
```
@ -27,35 +27,35 @@ fn main() {
struct Unit;
trait SomeTrait {
// ...Some behavours defines here
// ...Some behaviors defined here.
}
// We don't care the the fields are in Unit, but we care its behaviors.
// We don't care about what fields are in the Unit, but we care about its behaviors.
// So we use a struct with no fields and implement some behaviors for it
impl SomeTrait for Unit { }
fn main() {
let u = Unit;
do_something_with_unit(u);
println!("Success!")
println!("Success!");
}
// fill the blank to make the code work
// Fill the blank to make the code work
fn do_something_with_unit(u: __) { }
```
3. 🌟🌟🌟 Tuple struct looks similar to tuples, it has added meaning the struct name provides but has no named fields. It's useful when you want give the whole tuple a name, but don't care the fields's names.
3. 🌟🌟🌟 Tuple struct looks similar to tuples, it has added meaning the struct name provides but has no named fields. It's useful when you want to give the whole tuple a name, but don't care about the fields's names.
```rust,editable
// fix the error and fill the blanks
// Fix the error and fill the blanks
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
fn main() {
let v = Point(__, __, __);
check_color(v);
println!("Success!")
println!("Success!");
}
fn check_color(p: Color) {
@ -66,13 +66,13 @@ fn check_color(p: Color) {
}
```
### Operate on structs
### Operating on structs
4. 🌟 You can make a whole struct mutable when instantiate it, but Rust doesn't allow us to mark only certain fields as mutable.
4. 🌟 You can make a whole struct mutable when instantiating it, but Rust doesn't allow us to mark only certain fields as mutable.
```rust,editable
// fill the blank and fix the error without adding/removing new line
// Fill the blank and fix the error without adding/removing new line
struct Person {
name: String,
age: u8,
@ -84,26 +84,26 @@ fn main() {
age,
};
// how can you believe sunface is only 18?
// How can you believe sunface is only 18?
p.age = 30;
// fill the lank
// Fill the blank
__ = String::from("sunfei");
println!("Success!")
println!("Success!");
}
```
5. 🌟 Using *field init shorthand syntax* to reduct repetitions.
5. 🌟 Using *field init shorthand syntax* to reduce repetitions.
```rust,editable
// fill the blank
// Fill the blank
struct Person {
name: String,
age: u8,
}
fn main() {
println!("Success!")
println!("Success!");
}
fn build_person(name: String, age: u8) -> Person {
@ -117,7 +117,7 @@ fn build_person(name: String, age: u8) -> Person {
6. 🌟 You can create instance from other instance with *struct update syntax*
```rust,editable
// fill the blank to make the code work
// Fill the blank to make the code work
struct User {
active: bool,
username: String,
@ -134,7 +134,7 @@ fn main() {
let u2 = set_email(u1);
println!("Success!")
println!("Success!");
}
fn set_email(u: User) -> User {
@ -146,11 +146,11 @@ fn set_email(u: User) -> User {
```
### Print the structs
7. 🌟🌟 We can use `#[derive(Debug)]` to [make a struct prinable](https://doc.rust-lang.org/book/ch05-02-example-structs.html?highlight=%23%5Bderive(Debug)%5D#adding-useful-functionality-with-derived-traits).
7. 🌟🌟 We can use `#[derive(Debug)]` to [make a struct printable](https://doc.rust-lang.org/book/ch05-02-example-structs.html?highlight=%23%5Bderive(Debug)%5D#adding-useful-functionality-with-derived-traits).
```rust,editable
// fill the blanks to make the code work
// Fill the blanks to make the code work
#[__]
struct Rectangle {
width: u32,
@ -160,13 +160,13 @@ struct Rectangle {
fn main() {
let scale = 2;
let rect1 = Rectangle {
width: dbg!(30 * scale), // print debug info to stderr and assign the value of `30 * scale` to `width`
width: dbg!(30 * scale), // Print debug info to stderr and assign the value of `30 * scale` to `width`
height: 50,
};
dbg!(&rect1); // print debug info to stderr
dbg!(&rect1); // Print debug info to stderr
println!(__, rect1); // print debug info to stdout
println!(__, rect1); // Print debug info to stdout
}
```
@ -209,7 +209,7 @@ fn main() {
8. 🌟🌟
```rust,editable
// fix errors to make it work
// Fix errors to make it work
#[derive(Debug)]
struct File {
name: String,

View File

@ -6,29 +6,29 @@ fn main() {
let _t0: (u8,i16) = (0, -1);
// Tuples can be tuple's members
let _t1: (u8, (i16, u32)) = (0, (-1, 1));
// fill the blanks to make the code work
// Fill the blanks to make the code work
let t: (u8, __, i64, __, __) = (1u8, 2u16, 3i64, "hello", String::from(", world"));
println!("Success!")
println!("Success!");
}
```
2. 🌟 Members can be extracted from the tuple using indexing.
```rust,editable
// make it works
// Make it work
fn main() {
let t = ("i", "am", "sunface");
assert_eq!(t.1, "sunface");
println!("Success!")
println!("Success!");
}
```
3. 🌟 Long tuples cannot be printed
```rust,editable
// fix the error
// Fix the error
fn main() {
let too_long_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
println!("too long tuple: {:?}", too_long_tuple);
@ -41,14 +41,14 @@ fn main() {
fn main() {
let tup = (1, 6.4, "hello");
// fill the blank to make the code work
// Fill the blank to make the code work
let __ = tup;
assert_eq!(x, 1);
assert_eq!(y, "hello");
assert_eq!(z, 6.4);
println!("Success!")
println!("Success!");
}
```
@ -57,14 +57,14 @@ fn main() {
fn main() {
let (x, y, z);
// fill the blank
// Fill the blank
__ = (1, 2, 3);
assert_eq!(x, 3);
assert_eq!(y, 1);
assert_eq!(z, 2);
println!("Success!")
println!("Success!");
}
```
@ -72,13 +72,13 @@ fn main() {
```rust,editable
fn main() {
// fill the blank, need a few computations here.
// Fill the blank, need a few computations here.
let (x, y) = sum_multiply(__);
assert_eq!(x, 5);
assert_eq!(y, 6);
println!("Success!")
println!("Success!");
}
fn sum_multiply(nums: (i32, i32)) -> (i32, i32) {