Rust Closures: The Stateful Function Factory
Rust's closures are powerful tools for creating anonymous functions that can capture their environment. This challenge will test your understanding of how closures capture variables by value and by reference, and how to use them to create functions that maintain state.
Problem Description
You are tasked with creating a function that generates "counters". Each counter should be an independent entity that, when called, returns the next number in its sequence. The generated counters should be able to be called multiple times, each time yielding a progressively larger integer. This demonstrates how closures can "remember" and modify their captured state.
Your goal is to implement a function create_counter() that returns a closure. This closure, when invoked, should:
- Increment an internal counter by 1.
- Return the current value of the counter.
You need to ensure that each counter created by create_counter() is distinct and maintains its own independent count.
Examples
Example 1:
let mut counter1 = create_counter();
println!("{}", counter1()); // Output: 1
println!("{}", counter1()); // Output: 2
Explanation: create_counter() is called once, creating counter1. The first call to counter1() returns 1. The second call increments the internal state and returns 2.
Example 2:
let mut counter1 = create_counter();
let mut counter2 = create_counter();
println!("{}", counter1()); // Output: 1
println!("{}", counter2()); // Output: 1
println!("{}", counter1()); // Output: 2
println!("{}", counter2()); // Output: 2
println!("{}", counter1()); // Output: 3
Explanation: Two independent counters, counter1 and counter2, are created. Each maintains its own sequence of numbers.
Example 3:
let mut counter = create_counter();
// Imagine we need to reset or get the value without incrementing
// For this challenge, we focus on incrementing and returning.
// If you want to experiment with other closure behaviors, consider
// how `FnMut` and `FnOnce` play a role.
Explanation: This example highlights that the core requirement is incrementing and returning. Further exploration into different closure traits is encouraged but not mandatory for solving the primary task.
Constraints
- The
create_counterfunction must return a type that implementsFnMut() -> i32. - The generated counter closure must start its sequence at 1.
- The counter must handle an arbitrarily large number of calls without overflow within typical
i32limits.
Notes
- Closures in Rust can capture variables from their surrounding scope. Think about how you want to store the state of each counter.
- Consider the difference between
Fn,FnMut, andFnOnce. Which one is appropriate for a closure that needs to modify its captured state? - The
movekeyword can be useful when dealing with captured variables, especially if the closure needs to own them.