Compare commits

...

10 commits

Author SHA1 Message Date
Kacper Poneta 3343e4fdfb
Merge 59e8f70e55 into 47976caa69 2024-08-24 00:41:26 +01:00
mo8it 47976caa69 Import Ordering 2024-08-22 14:42:17 +02:00
mo8it f1abd8577c Add missing Clippy allows to solutions 2024-08-22 14:41:25 +02:00
mo8it 423b50b068 Use match instead of comparison chain 2024-08-22 14:37:47 +02:00
mo8it bedf0789f2 Always use strict Clippy when checking solutions 2024-08-22 14:25:14 +02:00
mo8it 59e8f70e55 Format code 2024-07-12 18:31:23 +02:00
mo8it 4c8365fe88 Update dev/Cargo.toml 2024-07-12 18:25:01 +02:00
Kacper Poneta 52af0674c1 changed the task to make it more appropriate 2024-07-12 18:14:40 +02:00
Kacper Poneta 938b90e5f2 very small solution update 2024-07-11 22:55:48 +02:00
Kacper Poneta 55cc8584bd added exercise 2024-07-11 22:53:38 +02:00
9 changed files with 133 additions and 17 deletions

View file

@ -116,6 +116,8 @@ bin = [
{ name = "generics1_sol", path = "../solutions/14_generics/generics1.rs" },
{ name = "generics2", path = "../exercises/14_generics/generics2.rs" },
{ name = "generics2_sol", path = "../solutions/14_generics/generics2.rs" },
{ name = "generics3", path = "../exercises/14_generics/generics3.rs" },
{ name = "generics3_sol", path = "../solutions/14_generics/generics3.rs" },
{ name = "traits1", path = "../exercises/15_traits/traits1.rs" },
{ name = "traits1_sol", path = "../solutions/15_traits/traits1.rs" },
{ name = "traits2", path = "../exercises/15_traits/traits2.rs" },

View file

@ -1,5 +1,3 @@
#![allow(clippy::comparison_chain)]
#[derive(PartialEq, Debug)]
enum CreationError {
Negative,

View file

@ -0,0 +1,54 @@
// generics3.rs
// Execute `rustlings hint generics3` or use the `hint` watch subcommand for a hint.
// This function should take an array of `Option` elements and returns array of not None elements
// TODO fix this function signature
fn into_dispose_nulls(list: Vec<Option<&str>>) -> Vec<&str> {
list.into_iter().flatten().collect()
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn store_str_on_list() {
let names_list = vec![Some("maria"), Some("jacob"), None, Some("kacper"), None];
let only_values = into_dispose_nulls(names_list);
assert_eq!(only_values.len(), 3);
}
#[test]
fn store_numbers_on_list() {
let numbers_list = vec![Some(1), Some(2), None, Some(3)];
let only_values = into_dispose_nulls(numbers_list);
assert_eq!(only_values.len(), 3);
}
#[test]
fn store_custom_type_on_list() {
#[allow(dead_code)]
struct Rectangle {
width: i32,
height: i32,
}
impl Rectangle {
fn new(width: i32, height: i32) -> Self {
Self { width, height }
}
}
let custom_list = vec![
Some(Rectangle::new(1, 2)),
None,
None,
Some(Rectangle::new(3, 4)),
];
let only_values = into_dispose_nulls(custom_list);
assert_eq!(only_values.len(), 2);
}
}

View file

@ -744,6 +744,17 @@ hint = """
Related section in The Book:
https://doc.rust-lang.org/book/ch10-01-syntax.html#in-method-definitions"""
[[exercises]]
name = "generics3"
dir = "14_generics"
hint = """
Vectors in Rust use generics to create dynamically-sized arrays of any type.
The `into_dispose_nulls` function takes a vector as an argument, but only accepts vectors that store the &str type.
To allow the function to accept vectors that store any type, you can leverage your knowledge about generics.
If you're unsure how to proceed, please refer to the Rust Book at:
https://doc.rust-lang.org/book/ch10-01-syntax.html#in-function-definitions.
"""
# TRAITS
[[exercises]]

View file

@ -18,12 +18,11 @@ fn main() {
// Here, both answers work.
// `.into()` converts a type into an expected type.
// If it is called where `String` is expected, it will convert `&str` to `String`.
// But if is called where `&str` is expected, then `&str` is kept `&str` since no
// conversion is needed.
string("nice weather".into());
// 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.
#[allow(clippy::useless_conversion)]
string_slice("nice weather".into());
// ^^^^^^^ the compiler recommends removing the `.into()`
// call because it is a useless conversion.
string(format!("Interpolation {}", "Station"));

View file

@ -1,4 +1,4 @@
#![allow(clippy::comparison_chain)]
use std::cmp::Ordering;
#[derive(PartialEq, Debug)]
enum CreationError {
@ -11,12 +11,10 @@ struct PositiveNonzeroInteger(u64);
impl PositiveNonzeroInteger {
fn new(value: i64) -> Result<Self, CreationError> {
if value == 0 {
Err(CreationError::Zero)
} else if value < 0 {
Err(CreationError::Negative)
} else {
Ok(Self(value as u64))
match value.cmp(&0) {
Ordering::Less => Err(CreationError::Negative),
Ordering::Equal => Err(CreationError::Zero),
Ordering::Greater => Ok(Self(value as u64)),
}
}
}

View file

@ -0,0 +1,53 @@
// generics3.rs
// Execute `rustlings hint generics3` or use the `hint` watch subcommand for a hint.
// Here we added generic type `T` to function signature
// Now this function can be used with vector of any
fn into_dispose_nulls<T>(list: Vec<Option<T>>) -> Vec<T> {
list.into_iter().flatten().collect()
}
fn main() {
// You can optionally experiment here.
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn store_str_on_list() {
let names_list = vec![Some("maria"), Some("jacob"), None, Some("kacper"), None];
let only_values = into_dispose_nulls(names_list);
assert_eq!(only_values.len(), 3);
}
#[test]
fn store_numbers_on_list() {
let numbers_list = vec![Some(1), Some(2), None, Some(3)];
let only_values = into_dispose_nulls(numbers_list);
assert_eq!(only_values.len(), 3);
}
#[test]
fn store_custom_type_on_list() {
struct Rectangle {
width: i32,
height: i32,
}
impl Rectangle {
fn new(width: i32, height: i32) -> Self {
Self { width, height }
}
}
let custom_list = vec![
Some(Rectangle::new(1, 2)),
None,
None,
Some(Rectangle::new(3, 4)),
];
let only_values = into_dispose_nulls(custom_list);
assert_eq!(only_values.len(), 2);
}
}

View file

@ -25,6 +25,7 @@ fn factorial_fold(num: u64) -> u64 {
// -> 1 * 2 is calculated, then the result 2 is multiplied by
// the second element 3 so the result 6 is returned.
// And so on…
#[allow(clippy::unnecessary_fold)]
(2..=num).fold(1, |acc, x| acc * x)
}

View file

@ -72,7 +72,7 @@ pub trait RunnableExercise {
// Compile, check and run the exercise or its solution (depending on `bin_name´).
// The output is written to the `output` buffer after clearing it.
fn run(
fn run<const FORCE_STRICT_CLIPPY: bool>(
&self,
bin_name: &str,
mut output: Option<&mut Vec<u8>>,
@ -115,7 +115,7 @@ pub trait RunnableExercise {
let mut clippy_cmd = cmd_runner.cargo("clippy", bin_name, output.as_deref_mut());
// `--profile test` is required to also check code with `[cfg(test)]`.
if self.strict_clippy() {
if FORCE_STRICT_CLIPPY || self.strict_clippy() {
clippy_cmd.args(["--profile", "test", "--", "-D", "warnings"]);
} else {
clippy_cmd.args(["--profile", "test"]);
@ -131,7 +131,7 @@ pub trait RunnableExercise {
/// The output is written to the `output` buffer after clearing it.
#[inline]
fn run_exercise(&self, output: Option<&mut Vec<u8>>, cmd_runner: &CmdRunner) -> Result<bool> {
self.run(self.name(), output, cmd_runner)
self.run::<false>(self.name(), output, cmd_runner)
}
/// Compile, check and run the exercise's solution.
@ -142,7 +142,7 @@ pub trait RunnableExercise {
bin_name.push_str(name);
bin_name.push_str("_sol");
self.run(&bin_name, output, cmd_runner)
self.run::<true>(&bin_name, output, cmd_runner)
}
}