diff --git a/en/src/generics-traits/advanced-traits.md b/en/src/generics-traits/advanced-traits.md index c761aba..7355dea 100644 --- a/en/src/generics-traits/advanced-traits.md +++ b/en/src/generics-traits/advanced-traits.md @@ -9,7 +9,7 @@ pub trait CacheableItem: Clone + Default + fmt::Debug + Decodable + Encodable { } ``` -Using of `Address` is much more clearable and convenient than `AsRef<[u8]> + Clone + fmt::Debug + Eq + Hash`. +Using of `Address` is much more clearer and convenient than `AsRef<[u8]> + Clone + fmt::Debug + Eq + Hash`. 1. ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ ```rust,editable @@ -89,7 +89,7 @@ fn main() { assert_eq!(Point { x: 2, y: 3 } - Point { x: 1, y: 0 }, Point { x: 1, y: 3 }); - println!("Success!") + println!("Success!"); } ``` @@ -110,7 +110,7 @@ trait AgeWidget { fn get(&self) -> u8; } -// A form with both a UsernameWidget and an AgeWidget +// A form with both a UsernameWidget and an AgeWidget. struct Form { username: String, age: u8, @@ -141,10 +141,10 @@ fn main() { let username = UsernameWidget::get(&form); assert_eq!("rustacean".to_owned(), username); - let age = AgeWidget::get(&form); // you can also use `
::get` + let age = AgeWidget::get(&form); // You can also use `::get` assert_eq!(28, age); - println!("Success!") + println!("Success!"); } ``` @@ -187,7 +187,7 @@ fn main() { assert_eq!(__, "*waving arms furiously*"); - println!("Success!") + println!("Success!"); } ``` @@ -253,7 +253,7 @@ fn main() { ## Orphan Rules We canโ€™t implement external traits on external types. For example, we canโ€™t implement the `Display` trait on `Vec` within our own crate, because `Display` and `Vec` are defined in the standard library and arenโ€™t local to our crate. -This restriction is often called as the orphan rule, so named because the parent type is not present. This rule ensures that other peopleโ€™s code canโ€™t break your code and vice versa. +This restriction is often called the orphan rule, so named because the parent type is not present. This rule ensures that other peopleโ€™s code canโ€™t break your code and vice versa. Itโ€™s possible to get around this restriction using the newtype pattern, which involves creating a new type in a tuple struct. diff --git a/en/src/generics-traits/const-generics.md b/en/src/generics-traits/const-generics.md index 3da51a3..660cee5 100644 --- a/en/src/generics-traits/const-generics.md +++ b/en/src/generics-traits/const-generics.md @@ -25,15 +25,15 @@ impl Debug for ArrayPair { fn foo() {} fn bar() { - foo::(); // ok: `M` is a const parameter - foo::<2021>(); // ok: `2021` is a literal - foo::<{20 * 100 + 20 * 10 + 1}>(); // ok: const expression contains no generic parameters + foo::(); // Okay: `M` is a const parameter + foo::<2021>(); // Okay: `2021` is a literal + foo::<{20 * 100 + 20 * 10 + 1}>(); // Okay: const expression contains no generic parameters - foo::<{ M + 1 }>(); // error: const expression contains the generic parameter `M` - foo::<{ std::mem::size_of::() }>(); // error: const expression contains the generic parameter `T` + foo::<{ M + 1 }>(); // Error: const expression contains the generic parameter `M` + foo::<{ std::mem::size_of::() }>(); // Error: const expression contains the generic parameter `T` - let _: [u8; M]; // ok: `M` is a const parameter - let _: [u8; std::mem::size_of::()]; // error: const expression contains the generic parameter `T` + let _: [u8; M]; // Okay: `M` is a const parameter + let _: [u8; std::mem::size_of::()]; // Error: const expression contains the generic parameter `T` } fn main() {} @@ -89,14 +89,14 @@ fn main() { } ]; - println!("Success!") + println!("Success!"); } ``` 2. ๐ŸŒŸ๐ŸŒŸ ```rust,editable -// fill in the blanks to make it work +// Fill in the blanks to make it work. fn print_array<__>(__) { println!("{:?}", arr); } @@ -109,7 +109,7 @@ fn main() { } ``` -3. ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ Sometimes we want to limit the size of an variable, e.g when using in embedding evironments, then `const expressions` will fit your need. +3. ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ Sometimes we want to limit the size of a variable, e.g when using in embedding environments, then `const expressions` will fit your needs. ```rust,editable #![allow(incomplete_features)] @@ -122,15 +122,15 @@ where //... } -// fix the errors in main +// Fix the errors in main. fn main() { check_size([0u8; 767]); check_size([0i32; 191]); - check_size(["helloไฝ ๅฅฝ"; __]); // size of &str ? - check_size(["helloไฝ ๅฅฝ".to_string(); __]); // size of String? - check_size(['ไธญ'; __]); // size of char ? + check_size(["helloไฝ ๅฅฝ"; __]); // Size of &str ? + check_size(["helloไฝ ๅฅฝ".to_string(); __]); // Size of String? + check_size(['ไธญ'; __]); // Size of char ? - println!("Success!") + println!("Success!"); } diff --git a/en/src/generics-traits/generics.md b/en/src/generics-traits/generics.md index dce2a14..a936610 100644 --- a/en/src/generics-traits/generics.md +++ b/en/src/generics-traits/generics.md @@ -4,7 +4,7 @@ 1. ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ ```rust,editable -// fill in the blanks to make it work +// Fill in the blanks to make it work struct A; // Concrete type `A`. struct S(A); // Concrete type `S`. struct SGen(T); // Generic type `SGen`. @@ -29,14 +29,14 @@ fn main() { // Implicitly specified type parameter `char` to `generic()`. generic(__); - println!("Success!") + println!("Success!"); } ``` 2. ๐ŸŒŸ๐ŸŒŸ A function call with explicitly specified type parameters looks like: `fun::()`. ```rust,editable -// implement the generic function below +// Implement the generic function below. fn sum fn main() { @@ -44,7 +44,7 @@ fn main() { assert_eq!(50, sum(20, 30)); assert_eq!(2.46, sum(1.23, 1.23)); - println!("Success!") + println!("Success!"); } ``` @@ -54,38 +54,38 @@ fn main() { 3. ๐ŸŒŸ ```rust,editable -// implement struct Point to make it work +// Implement struct Point to make it work. fn main() { let integer = Point { x: 5, y: 10 }; let float = Point { x: 1.0, y: 4.0 }; - println!("Success!") + println!("Success!"); } ``` 4. ๐ŸŒŸ๐ŸŒŸ ```rust,editable -// modify this struct to make the code work +// Modify this struct to make the code work struct Point { x: T, y: T, } fn main() { - // DON'T modify here + // DON'T modify this code. let p = Point{x: 5, y : "hello".to_string()}; - println!("Success!") + println!("Success!"); } ``` 5. ๐ŸŒŸ๐ŸŒŸ ```rust,editable -// add generic for Val to make the code work, DON'T modify the code in `main` +// Add generic for Val to make the code work, DON'T modify the code in `main`. struct Val { val: f64, } @@ -114,7 +114,7 @@ struct Point { } impl Point { - // implement mixup to make it work, DON'T modify other code + // Implement mixup to make it work, DON'T modify other code. fn mixup } @@ -127,14 +127,14 @@ fn main() { assert_eq!(p3.x, 5); assert_eq!(p3.y, 'ไธญ'); - println!("Success!") + println!("Success!"); } ``` 7. ๐ŸŒŸ๐ŸŒŸ ```rust,editable -// fix the errors to make the code work +// Fix the errors to make the code work. struct Point { x: T, y: T, @@ -148,7 +148,7 @@ impl Point { fn main() { let p = Point{x: 5, y: 10}; - println!("{}",p.distance_from_origin()) + println!("{}",p.distance_from_origin()); } ``` diff --git a/en/src/generics-traits/trait-object.md b/en/src/generics-traits/trait-object.md index 411b49a..4c45a7f 100644 --- a/en/src/generics-traits/trait-object.md +++ b/en/src/generics-traits/trait-object.md @@ -4,7 +4,7 @@ In [traits chapter](https://practice.rs/generics-traits/traits.html#returning-ty Also one limitation of arrays is that they can only store elements of one type, yeah, enum is a not bad solution when our items are a fixed set of types in compile time, but trait object are more flexible and powerful here. ## Returning Traits with dyn -The Rust compiler needs to know how much space a function's return type requires. Because the different implementations of a trait probably will need different amounts of memoery, this means function need to return a concrete type or the same type when using `impl Trait`, or it can return a trait object with `dyn`. +The Rust compiler needs to know how much space a function's return type requires. Because the different implementations of a trait probably will need different amounts of memory, this means function need to return a concrete type or the same type when using `impl Trait`, or it can return a trait object with `dyn`. 1. ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ ```rust,editable @@ -39,26 +39,26 @@ impl Bird for Swan { } fn main() { - // FILL in the blank + // FILL in the blank. let duck = __; duck.swim(); let bird = hatch_a_bird(2); - // this bird has forgotten how to swim, so below line will cause an error + // This bird has forgotten how to swim, so below line will cause an error. // bird.swim(); - // but it can quak + // But it can quak. assert_eq!(bird.quack(), "duck duck"); let bird = hatch_a_bird(1); - // this bird has forgotten how to fly, so below line will cause an error + // This bird has forgotten how to fly, so below line will cause an error. // bird.fly(); - // but it can quak too + // But it can quak too. assert_eq!(bird.quack(), "swan swan"); - println!("Success!") + println!("Success!"); } -// IMPLEMENT this function +// IMPLEMENT this function. fn hatch_a_bird... ``` @@ -95,13 +95,13 @@ impl Bird for Swan { } fn main() { - // FILL in the blank to make the code work + // FILL in the blank to make the code work. let birds __; for bird in birds { bird.quack(); - // when duck and swan turns into Bird, they all forgot how to fly, only remeber how to quack - // so, the below code will cause an error + // When duck and swan turn into Birds, they all forgot how to fly, only remember how to quack. + // So, the code below will cause an error. // bird.fly(); } } @@ -113,7 +113,7 @@ fn main() { 3. ๐ŸŒŸ๐ŸŒŸ ```rust,editable -// FILL in the blanks +// FILL in the blanks. trait Draw { fn draw(&self) -> String; } @@ -134,13 +134,13 @@ fn main() { let x = 1.1f64; let y = 8u8; - // draw x + // Draw x. draw_with_box(__); - // draw y + // Draw y. draw_with_ref(&y); - println!("Success!") + println!("Success!"); } fn draw_with_box(x: Box) { @@ -153,11 +153,11 @@ fn draw_with_ref(x: __) { ``` ## Static and Dynamic dispatch -when we use trait bounds on generics: the compiler generates nongeneric implementations of functions and methods for each concrete type that we use in place of a generic type parameter. The code that results from monomorphization is doing static dispatch, which is when the compiler knows what method youโ€™re calling at compile time. +When we use trait bounds on generics, the compiler generates nongeneric implementations of functions and methods for each concrete type that we use in place of a generic type parameter. The code that results from monomorphization is doing static dispatch, which is when the compiler knows what method youโ€™re calling at compile time. When we use trait objects, Rust must use dynamic dispatch. The compiler doesnโ€™t know all the types that might be used with the code that is using trait objects, so it doesnโ€™t know which method implemented on which type to call. Instead, at runtime, Rust uses the pointers inside the trait object to know which method to call. There is a runtime cost when this lookup happens that doesnโ€™t occur with static dispatch. Dynamic dispatch also prevents the compiler from choosing to inline a methodโ€™s code, which in turn prevents some optimizations. -However, we did get extra flexibility when using dynamic dispatch. +However, we do get extra flexibility when using dynamic dispatch. 4. ๐ŸŒŸ๐ŸŒŸ ```rust,editable @@ -174,10 +174,10 @@ impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } } -// IMPLEMENT below with generics +// IMPLEMENT below with generics. fn static_dispatch... -// implement below with trait objects +// Implement below with trait objects. fn dynamic_dispatch... fn main() { @@ -187,7 +187,7 @@ fn main() { static_dispatch(x); dynamic_dispatch(&y); - println!("Success!") + println!("Success!"); } ``` @@ -200,8 +200,8 @@ You can only make object-safe traits into trait objects. A trait is object safe 5. ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ ```rust,editable -// Use at least two approaches to make it work -// DON'T add/remove any code line +// Use at least two approaches to make it work. +// DON'T add/remove any code line. trait MyTrait { fn f(&self) -> Self; } @@ -222,7 +222,7 @@ fn main() { my_function(Box::new(13_u32)); my_function(Box::new(String::from("abc"))); - println!("Success!") + println!("Success!"); } ``` diff --git a/en/src/generics-traits/traits.md b/en/src/generics-traits/traits.md index 3f09e4c..57a861d 100644 --- a/en/src/generics-traits/traits.md +++ b/en/src/generics-traits/traits.md @@ -81,8 +81,8 @@ fn main() { 1. ๐ŸŒŸ๐ŸŒŸ ```rust,editable -// fill in the two impl blocks to make the code work -// DON'T modify the code in `main` +// Fill in the two impl blocks to make the code work. +// DON'T modify the code in `main`. trait Hello { fn say_hi(&self) -> String { String::from("hi") @@ -107,7 +107,7 @@ fn main() { assert_eq!(t.say_hi(), "Hi, I'm your new teacher"); assert_eq!(t.say_something(), "I'm not a bad teacher"); - println!("Success!") + println!("Success!"); } ``` @@ -135,7 +135,7 @@ impl Inches { } // ADD some attributes to make the code work! -// DON'T modify other codes! +// DON'T modify other code! struct Seconds(i32); fn main() { @@ -171,23 +171,23 @@ In Rust, many of the operators can be overloaded via traits. That is, some opera use std::ops; -// implement fn multiply to make the code work -// As mentiond above, `+` needs `T` to implement `std::ops::Add` Trait -// so, what about `*` ? You can find the answer here: https://doc.rust-lang.org/core/ops/ +// Implement fn multiply to make the code work. +// As mentiond above, `+` needs `T` to implement `std::ops::Add` Trait. +// So, what about `*`? You can find the answer here: https://doc.rust-lang.org/core/ops/ fn multipl fn main() { assert_eq!(6, multiply(2u8, 3u8)); assert_eq!(5.0, multiply(1.0, 5.0)); - println!("Success!") + println!("Success!"); } ``` 4. ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ ```rust,editable -// fix the errors, DON'T modify the code in `main` +// Fix the errors, DON'T modify the code in `main`. use std::ops; struct Foo; @@ -217,12 +217,12 @@ impl ops::Sub for Bar { } fn main() { - // DON'T modify the below code - // you need to derive some trait for FooBar to make it comparable + // DON'T modify the code below. + // You need to derive some trait for FooBar to make it comparable. assert_eq!(Foo + Bar, FooBar); assert_eq!(Foo - Bar, BarFoo); - println!("Success!") + println!("Success!"); } ``` @@ -232,8 +232,8 @@ Instead of a concrete type for the item parameter, we specify the impl keyword a 5. ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ ```rust,editable -// implement `fn summary` to make the code work -// fix the errors without removing any code line +// Implement `fn summary` to make the code work. +// Fix the errors without removing any code line trait Summary { fn summarize(&self) -> String; } @@ -281,14 +281,14 @@ fn main() { println!("{:?}", weibo); } -// implement `fn summary` below +// Implement `fn summary` below. ``` ### Returning Types that Implement Traits We can also use the impl Trait syntax in the return position to return a value of some type that implements a trait. -However, you can only use impl Trait if youโ€™re returning a single type, using Trait Objects instead when you really need to return serveral types. +However, you can only use impl Trait if youโ€™re returning a single type, use Trait Objects instead when you really need to return several types. 6. ๐ŸŒŸ๐ŸŒŸ ```rust,editable @@ -313,7 +313,7 @@ impl Animal for Cow { } // Returns some struct that implements Animal, but we don't know which one at compile time. -// FIX the erros here, you can make a fake random, or you can use trait object +// FIX the errors here, you can make a fake random, or you can use trait object. fn random_animal(random_number: f64) -> impl Animal { if random_number < 0.5 { Sheep {} @@ -340,7 +340,7 @@ fn main() { assert_eq!(sum(1, 2), 3); } -// implement `fn sum` with trait bound in two ways +// Implement `fn sum` with trait bound in two ways. fn sum(x: T, y: T) -> T { x + y } @@ -348,7 +348,7 @@ fn sum(x: T, y: T) -> T { 8. ๐ŸŒŸ๐ŸŒŸ ```rust,editable -// FIX the errors +// FIX the errors. struct Pair { x: T, y: T, @@ -388,10 +388,10 @@ fn main() { 9. ๐ŸŒŸ๐ŸŒŸ๐ŸŒŸ ```rust,editable -// fill in the blanks to make it work +// Fill in the blanks to make it work fn example1() { - // `T: Trait` is the commonly used way - // `T: Fn(u32) -> u32` specifies that we can only pass a closure to `T` + // `T: Trait` is the commonly used way. + // `T: Fn(u32) -> u32` specifies that we can only pass a closure to `T`. struct Cacher u32> { calculation: T, value: Option, @@ -424,7 +424,7 @@ fn example1() { fn example2() { - // We can also use `where` to constrain `T` + // We can also use `where` to construct `T` struct Cacher where T: Fn(u32) -> u32, { @@ -465,7 +465,7 @@ fn main() { example1(); example2(); - println!("Success!") + println!("Success!"); } ```