mirror of
https://github.com/rust-lang/rustlings.git
synced 2025-12-28 14:59:18 +00:00
Compare commits
No commits in common. "main" and "v6.5.0" have entirely different histories.
@ -1,9 +1,5 @@
|
|||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- `vecs2`: Removed the use of `map` and `collect`, which are only taught later.
|
|
||||||
|
|
||||||
## 6.5.0 (2025-08-21)
|
## 6.5.0 (2025-08-21)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@ -9,6 +9,26 @@ fn vec_loop(input: &[i32]) -> Vec<i32> {
|
|||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn vec_map_example(input: &[i32]) -> Vec<i32> {
|
||||||
|
// An example of collecting a vector after mapping.
|
||||||
|
// We map each element of the `input` slice to its value plus 1.
|
||||||
|
// If the input is `[1, 2, 3]`, the output is `[2, 3, 4]`.
|
||||||
|
input.iter().map(|element| element + 1).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vec_map(input: &[i32]) -> Vec<i32> {
|
||||||
|
// TODO: Here, we also want to multiply each element in the `input` slice
|
||||||
|
// by 2, but with iterator mapping instead of manually pushing into an empty
|
||||||
|
// vector.
|
||||||
|
// See the example in the function `vec_map_example` above.
|
||||||
|
input
|
||||||
|
.iter()
|
||||||
|
.map(|element| {
|
||||||
|
// ???
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// You can optionally experiment here.
|
// You can optionally experiment here.
|
||||||
}
|
}
|
||||||
@ -23,4 +43,18 @@ mod tests {
|
|||||||
let ans = vec_loop(&input);
|
let ans = vec_loop(&input);
|
||||||
assert_eq!(ans, [4, 8, 12, 16, 20]);
|
assert_eq!(ans, [4, 8, 12, 16, 20]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vec_map_example() {
|
||||||
|
let input = [1, 2, 3];
|
||||||
|
let ans = vec_map_example(&input);
|
||||||
|
assert_eq!(ans, [2, 3, 4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vec_map() {
|
||||||
|
let input = [2, 4, 6, 8, 10];
|
||||||
|
let ans = vec_map(&input);
|
||||||
|
assert_eq!(ans, [4, 8, 12, 16, 20]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
// Here are some more easy Clippy fixes so you can see its utility.
|
// Here are some more easy Clippy fixes so you can see its utility 📎
|
||||||
// TODO: Fix all the Clippy lints.
|
// TODO: Fix all the Clippy lints.
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
#[allow(unused_variables, unused_assignments)]
|
#[allow(unused_variables, unused_assignments)]
|
||||||
fn main() {
|
fn main() {
|
||||||
let my_option: Option<&str> = None;
|
let my_option: Option<&str> = None;
|
||||||
@ -10,16 +11,14 @@ fn main() {
|
|||||||
println!("{}", my_option.unwrap());
|
println!("{}", my_option.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
let my_arr = &[
|
let my_arr = &[
|
||||||
-1, -2, -3
|
-1, -2, -3
|
||||||
-4, -5, -6
|
-4, -5, -6
|
||||||
];
|
];
|
||||||
println!("My array! Here it is: {my_arr:?}");
|
println!("My array! Here it is: {my_arr:?}");
|
||||||
|
|
||||||
let mut my_vec = vec![1, 2, 3, 4, 5];
|
let my_empty_vec = vec![1, 2, 3, 4, 5].resize(0, 5);
|
||||||
my_vec.resize(0, 5);
|
println!("This Vec is empty, see? {my_empty_vec:?}");
|
||||||
println!("This Vec is empty, see? {my_vec:?}");
|
|
||||||
|
|
||||||
let mut value_a = 45;
|
let mut value_a = 45;
|
||||||
let mut value_b = 66;
|
let mut value_b = 66;
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
| vecs | §8.1 |
|
| vecs | §8.1 |
|
||||||
| move_semantics | §4.1-2 |
|
| move_semantics | §4.1-2 |
|
||||||
| structs | §5.1, §5.3 |
|
| structs | §5.1, §5.3 |
|
||||||
| enums | §6, §19.3 |
|
| enums | §6, §18.3 |
|
||||||
| strings | §8.2 |
|
| strings | §8.2 |
|
||||||
| modules | §7 |
|
| modules | §7 |
|
||||||
| hashmaps | §8.3 |
|
| hashmaps | §8.3 |
|
||||||
|
|||||||
@ -318,7 +318,16 @@ of the Rust book to learn more."""
|
|||||||
name = "vecs2"
|
name = "vecs2"
|
||||||
dir = "05_vecs"
|
dir = "05_vecs"
|
||||||
hint = """
|
hint = """
|
||||||
Use the `.push()` method on the vector to push new elements to it."""
|
In the first function, we create an empty vector and want to push new elements
|
||||||
|
to it.
|
||||||
|
|
||||||
|
In the second function, we map the values of the input and collect them into
|
||||||
|
a vector.
|
||||||
|
|
||||||
|
After you've completed both functions, decide for yourself which approach you
|
||||||
|
like better.
|
||||||
|
|
||||||
|
What do you think is the more commonly used pattern under Rust developers?"""
|
||||||
|
|
||||||
# MOVE SEMANTICS
|
# MOVE SEMANTICS
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,22 @@ fn vec_loop(input: &[i32]) -> Vec<i32> {
|
|||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn vec_map_example(input: &[i32]) -> Vec<i32> {
|
||||||
|
// An example of collecting a vector after mapping.
|
||||||
|
// We map each element of the `input` slice to its value plus 1.
|
||||||
|
// If the input is `[1, 2, 3]`, the output is `[2, 3, 4]`.
|
||||||
|
input.iter().map(|element| element + 1).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vec_map(input: &[i32]) -> Vec<i32> {
|
||||||
|
// We will dive deeper into iterators, but for now, this is all what you
|
||||||
|
// had to do!
|
||||||
|
// Advanced note: This method is more efficient because it automatically
|
||||||
|
// preallocates enough capacity. This can be done manually in `vec_loop`
|
||||||
|
// using `Vec::with_capacity(input.len())` instead of `Vec::new()`.
|
||||||
|
input.iter().map(|element| 2 * element).collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// You can optionally experiment here.
|
// You can optionally experiment here.
|
||||||
}
|
}
|
||||||
@ -22,4 +38,18 @@ mod tests {
|
|||||||
let ans = vec_loop(&input);
|
let ans = vec_loop(&input);
|
||||||
assert_eq!(ans, [4, 8, 12, 16, 20]);
|
assert_eq!(ans, [4, 8, 12, 16, 20]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vec_map_example() {
|
||||||
|
let input = [1, 2, 3];
|
||||||
|
let ans = vec_map_example(&input);
|
||||||
|
assert_eq!(ans, [2, 3, 4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vec_map() {
|
||||||
|
let input = [2, 4, 6, 8, 10];
|
||||||
|
let ans = vec_map(&input);
|
||||||
|
assert_eq!(ans, [4, 8, 12, 16, 20]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@ fn main() {
|
|||||||
// `.into()` converts a type into an expected type.
|
// `.into()` converts a type into an expected type.
|
||||||
// If it is called where `String` is expected, it will convert `&str` to `String`.
|
// If it is called where `String` is expected, it will convert `&str` to `String`.
|
||||||
string("nice weather".into());
|
string("nice weather".into());
|
||||||
// But if it is called where `&str` is expected, then `&str` is kept as `&str` since no conversion is needed.
|
// But if it is called where `&str` is expected, then `&str` is kept `&str` since no conversion is needed.
|
||||||
// If you remove the `#[allow(…)]` line, then Clippy will tell you to remove `.into()` below since it is a useless conversion.
|
// If you remove the `#[allow(…)]` line, then Clippy will tell you to remove `.into()` below since it is a useless conversion.
|
||||||
#[allow(clippy::useless_conversion)]
|
#[allow(clippy::useless_conversion)]
|
||||||
string_slice("nice weather".into());
|
string_slice("nice weather".into());
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// A basket of fruits in the form of a hash map needs to be defined. The key
|
// A basket of fruits in the form of a hash map needs to be defined. The key
|
||||||
// represents the name of the fruit and the value represents how many of that
|
// represents the name of the fruit and the value represents how many of that
|
||||||
// particular fruit is in the basket. You have to put at least 3 different
|
// particular fruit is in the basket. You have to put at least 3 different
|
||||||
// types of fruits (e.g. apple, banana, mango) in the basket and the total count
|
// types of fruits (e.g apple, banana, mango) in the basket and the total count
|
||||||
// of all the fruits should be at least 5.
|
// of all the fruits should be at least 5.
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
// This function returns how much ice cream there is left in the fridge.
|
// This function returns how much icecream there is left in the fridge.
|
||||||
// If it's before 22:00 (24-hour system), then 5 scoops are left. At 22:00,
|
// If it's before 22:00 (24-hour system), then 5 scoops are left. At 22:00,
|
||||||
// someone eats it all, so no ice cream is left (value 0). Return `None` if
|
// someone eats it all, so no icecream is left (value 0). Return `None` if
|
||||||
// `hour_of_day` is higher than 23.
|
// `hour_of_day` is higher than 23.
|
||||||
fn maybe_ice_cream(hour_of_day: u16) -> Option<u16> {
|
fn maybe_icecream(hour_of_day: u16) -> Option<u16> {
|
||||||
match hour_of_day {
|
match hour_of_day {
|
||||||
0..=21 => Some(5),
|
0..=21 => Some(5),
|
||||||
22..=23 => Some(0),
|
22..=23 => Some(0),
|
||||||
@ -21,19 +21,19 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn raw_value() {
|
fn raw_value() {
|
||||||
// Using `unwrap` is fine in a test.
|
// Using `unwrap` is fine in a test.
|
||||||
let ice_creams = maybe_ice_cream(12).unwrap();
|
let icecreams = maybe_icecream(12).unwrap();
|
||||||
|
|
||||||
assert_eq!(ice_creams, 5);
|
assert_eq!(icecreams, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_ice_cream() {
|
fn check_icecream() {
|
||||||
assert_eq!(maybe_ice_cream(0), Some(5));
|
assert_eq!(maybe_icecream(0), Some(5));
|
||||||
assert_eq!(maybe_ice_cream(9), Some(5));
|
assert_eq!(maybe_icecream(9), Some(5));
|
||||||
assert_eq!(maybe_ice_cream(18), Some(5));
|
assert_eq!(maybe_icecream(18), Some(5));
|
||||||
assert_eq!(maybe_ice_cream(22), Some(0));
|
assert_eq!(maybe_icecream(22), Some(0));
|
||||||
assert_eq!(maybe_ice_cream(23), Some(0));
|
assert_eq!(maybe_icecream(23), Some(0));
|
||||||
assert_eq!(maybe_ice_cream(24), None);
|
assert_eq!(maybe_icecream(24), None);
|
||||||
assert_eq!(maybe_ice_cream(25), None);
|
assert_eq!(maybe_icecream(25), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
//
|
//
|
||||||
// In short, this particular use case for boxes is for when you want to own a
|
// In short, this particular use case for boxes is for when you want to own a
|
||||||
// value and you care only that it is a type which implements a particular
|
// value and you care only that it is a type which implements a particular
|
||||||
// trait. To do so, the `Box` is declared as of type `Box<dyn Trait>` where
|
// trait. To do so, The `Box` is declared as of type `Box<dyn Trait>` where
|
||||||
// `Trait` is the trait the compiler looks for on any value used in that
|
// `Trait` is the trait the compiler looks for on any value used in that
|
||||||
// context. For this exercise, that context is the potential errors which
|
// context. For this exercise, that context is the potential errors which
|
||||||
// can be returned in a `Result`.
|
// can be returned in a `Result`.
|
||||||
|
|||||||
@ -4,7 +4,7 @@ fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let string1 = String::from("long string is long");
|
let string1 = String::from("long string is long");
|
||||||
// Solution 1: You can move `strings2` out of the inner block so that it is
|
// Solution1: You can move `strings2` out of the inner block so that it is
|
||||||
// not dropped before the print statement.
|
// not dropped before the print statement.
|
||||||
let string2 = String::from("xyz");
|
let string2 = String::from("xyz");
|
||||||
let result;
|
let result;
|
||||||
@ -21,7 +21,7 @@ fn main() {
|
|||||||
{
|
{
|
||||||
let string2 = String::from("xyz");
|
let string2 = String::from("xyz");
|
||||||
result = longest(&string1, &string2);
|
result = longest(&string1, &string2);
|
||||||
// Solution 2: You can move the print statement into the inner block so
|
// Solution2: You can move the print statement into the inner block so
|
||||||
// that it is executed before `string2` is dropped.
|
// that it is executed before `string2` is dropped.
|
||||||
println!("The longest string is '{result}'");
|
println!("The longest string is '{result}'");
|
||||||
// `string2` dropped here (end of the inner scope).
|
// `string2` dropped here (end of the inner scope).
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
// Added the `macro_use` attribute.
|
// Added the attribute `macro_use` attribute.
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod macros {
|
mod macros {
|
||||||
macro_rules! my_macro {
|
macro_rules! my_macro {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
#[allow(unused_variables, unused_assignments)]
|
#[allow(unused_variables, unused_assignments)]
|
||||||
fn main() {
|
fn main() {
|
||||||
let my_option: Option<&str> = None;
|
let my_option: Option<&str> = None;
|
||||||
@ -10,18 +11,17 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A comma was missing.
|
// A comma was missing.
|
||||||
#[rustfmt::skip]
|
|
||||||
let my_arr = &[
|
let my_arr = &[
|
||||||
-1, -2, -3,
|
-1, -2, -3,
|
||||||
-4, -5, -6,
|
-4, -5, -6,
|
||||||
];
|
];
|
||||||
println!("My array! Here it is: {my_arr:?}");
|
println!("My array! Here it is: {my_arr:?}");
|
||||||
|
|
||||||
let mut my_vec = vec![1, 2, 3, 4, 5];
|
let mut my_empty_vec = vec![1, 2, 3, 4, 5];
|
||||||
// `resize` mutates a vector instead of returning a new one.
|
// `resize` mutates a vector instead of returning a new one.
|
||||||
// `resize(0, …)` clears a vector, so it is better to use `clear`.
|
// `resize(0, …)` clears a vector, so it is better to use `clear`.
|
||||||
my_vec.clear();
|
my_empty_vec.clear();
|
||||||
println!("This Vec is empty, see? {my_vec:?}");
|
println!("This Vec is empty, see? {my_empty_vec:?}");
|
||||||
|
|
||||||
let mut value_a = 45;
|
let mut value_a = 45;
|
||||||
let mut value_b = 66;
|
let mut value_b = 66;
|
||||||
|
|||||||
@ -74,7 +74,7 @@ pub fn init() -> Result<()> {
|
|||||||
|
|
||||||
let workspace_manifest_content = fs::read_to_string(&workspace_manifest)
|
let workspace_manifest_content = fs::read_to_string(&workspace_manifest)
|
||||||
.with_context(|| format!("Failed to read the file {}", workspace_manifest.display()))?;
|
.with_context(|| format!("Failed to read the file {}", workspace_manifest.display()))?;
|
||||||
if !workspace_manifest_content.contains("[workspace]")
|
if !workspace_manifest_content.contains("[workspace]\n")
|
||||||
&& !workspace_manifest_content.contains("workspace.")
|
&& !workspace_manifest_content.contains("workspace.")
|
||||||
{
|
{
|
||||||
bail!(
|
bail!(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user