diff --git a/Cargo.lock b/Cargo.lock index acbf473..4289a12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -221,6 +221,10 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +[[package]] +name = "closures" +version = "0.1.0" + [[package]] name = "colorchoice" version = "1.0.0" diff --git a/challenges/challenges.json b/challenges/challenges.json index c94c519..7475cdd 100644 --- a/challenges/challenges.json +++ b/challenges/challenges.json @@ -143,6 +143,18 @@ "created_at": "2024-06-12T00:00:00Z", "updated_at": "2024-06-12T00:00:00Z" }, + { + "id": 32, + "title": "Closures", + "slug": "closures", + "short_description": "Learn how to define and use closures in Rust.", + "language": "RUST", + "difficulty": "BEGINNER", + "track": "RUST_BASICS", + "tags": ["closures", "basics"], + "created_at": "2024-06-12T00:00:00Z", + "updated_at": "2024-06-12T00:00:00Z" + }, { "id": 2, "title": "Character counting string", diff --git a/challenges/closures/Cargo.toml b/challenges/closures/Cargo.toml new file mode 100644 index 0000000..2cb7c6f --- /dev/null +++ b/challenges/closures/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "closures" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/challenges/closures/description.md b/challenges/closures/description.md new file mode 100644 index 0000000..eb4a21c --- /dev/null +++ b/challenges/closures/description.md @@ -0,0 +1,51 @@ +Closures in Rust are anonymous functions that can **capture variables from their environment.** They are similar to functions but have some unique properties that make them powerful and flexible. Closures are often used for short, simple operations and can be defined in a very concise way. + +## Understanding Closures + +A closure is defined using a pair of vertical bars `|` that enclose the parameters, followed by the closure body. Here's a simple example of a closure that adds two numbers: + +```rust +let add = |a: i32, b: i32| a + b; +``` + +In this example, add is a closure that takes two parameters, `a` and `b`, and returns their **sum**. **You can call this closure just like a function**: + +```rust +let result = add(2, 3); // result is 5 +``` + +Closures can **capture variables** from their enclosing scope. For example: + +```rust +let x = 2; +let add_x = |a: i32| a + x; +let result = add_x(3); // result is 5 +``` + +In this case, the closure `add_x` captures the variable `x` from the surrounding scope and adds it to its parameter `a`. + +## Your task + +Your task is to complete the implementation of the following closures: + +- `add_closure`: This closure should return the **sum of two integers**. +- `subtract_closure`: This closure should return the **difference between two integers**. +- `multiply_closure`: This closure should return the **product of two integers**. + +## Requirements + +- Each closure should take two parameters of type `i32`. +- Each closure should return a result of type `i32`. + +## Example + +```rust +assert_eq!(add_closure(3, 4), 7); +assert_eq!(subtract_closure(10, 4), 6); +assert_eq!(multiply_closure(3, 5), 15); +``` + +## Hints + +- Remember to use the `let` keyword to define closures. +- Use the `|a, b|` syntax to define the parameters of the closure. diff --git a/challenges/closures/src/lib.rs b/challenges/closures/src/lib.rs new file mode 100644 index 0000000..11f9fb8 --- /dev/null +++ b/challenges/closures/src/lib.rs @@ -0,0 +1,11 @@ +pub fn create_closures() -> ( + impl Fn(i32, i32) -> i32, + impl Fn(i32, i32) -> i32, + impl Fn(i32, i32) -> i32, +) { + let add_closure = |a, b| a + b; + let subtract_closure = |a, b| a - b; + let multiply_closure = |a, b| a * b; + + (add_closure, subtract_closure, multiply_closure) +} diff --git a/challenges/closures/src/starter.rs b/challenges/closures/src/starter.rs new file mode 100644 index 0000000..64a6a7c --- /dev/null +++ b/challenges/closures/src/starter.rs @@ -0,0 +1,17 @@ +pub fn create_closures() -> ( + impl Fn(i32, i32) -> i32, + impl Fn(i32, i32) -> i32, + impl Fn(i32, i32) -> i32, +) { + let add_closure = |a, b| { + // Step 1: Implement here + }; + + // Step 2: + // Create the `subtract_closure` closure that subtracts two `i32` values. + + // Step 3: + // Create the `multiply_closure` closure that multiplies two `i32` values. + + (add_closure, subtract_closure, multiply_closure) +} diff --git a/challenges/closures/tests/tests.rs b/challenges/closures/tests/tests.rs new file mode 100644 index 0000000..06fdc42 --- /dev/null +++ b/challenges/closures/tests/tests.rs @@ -0,0 +1,28 @@ +#[cfg(test)] +mod tests { + use closures::*; + + #[test] + fn test_add_closure() { + let (add_closure, _, _) = create_closures(); + assert_eq!(add_closure(3, 4), 7); + assert_eq!(add_closure(-1, 1), 0); + assert_eq!(add_closure(0, 0), 0); + } + + #[test] + fn test_subtract_closure() { + let (_, subtract_closure, _) = create_closures(); + assert_eq!(subtract_closure(10, 4), 6); + assert_eq!(subtract_closure(4, 10), -6); + assert_eq!(subtract_closure(0, 0), 0); + } + + #[test] + fn test_multiply_closure() { + let (_, _, multiply_closure) = create_closures(); + assert_eq!(multiply_closure(3, 5), 15); + assert_eq!(multiply_closure(-2, 3), -6); + assert_eq!(multiply_closure(0, 10), 0); + } +}