Closure as struct member

The following is an example with a closure and a struct that uses it:

struct Calculator<T>
where
    T: Fn(f32, f32) -> f32,
{
    operation: T,
}

fn main() {
    // Define a closure for addition
    let add = |a, b| a + b;

    // Create an instance of Calculator with the addition closure
    let add_calculator = Calculator { operation: add };

    // Use the calculator to perform addition
    let result = (add_calculator.operation)(5.0, 3.0);

    println!("Result of addition: {}", result);

    // Define a closure for subtraction
    let subtract = |a, b| a - b;

    // Create another instance of Calculator with the subtraction closure
    let subtract_calculator = Calculator {
        operation: subtract,
    };

    // Use the calculator to perform subtraction
    let result = (subtract_calculator.operation)(10.0, 7.0);

    println!("Result of subtraction: {}", result);
}

In this example, we have a Calculator struct that takes a generic type parameter T, which is expected to be a closure. The closure should take two f32 arguments and return an f32. The struct has a single field named operation of type T.

In the main function:

  1. We define a closure add that takes two f32 arguments and returns their sum.
  2. We create an instance of the Calculator struct called add_calculator, initializing it with the add closure.
  3. We use the add_calculator to perform addition by invoking the closure with the arguments 5.0 and 3.0. The result is stored in the result variable and printed.
  4. Then, we define another closure subtract for subtraction and create a Calculator instance called subtract_calculator with the subtract closure.
  5. We use subtract_calculator to perform subtraction in a similar manner.

Webdock – Fast Cloud VPS Hosting


How to use closures as fields of structs



In both cases, the operation field of the Calculator struct holds a reference to a closure, and we call that closure with appropriate arguments to perform mathematical operations. This demonstrates how Rust allows you to use closures as fields of structs to achieve flexible behaviour.

The two sets of parentheses in the line let result = (subtract_calculator.operation)(10.0, 7.0); are used to first access and then immediately call the closure stored in the operation field of the subtract_calculator.

Here’s the breakdown of what’s happening:

  1. (subtract_calculator.operation) accesses the operation field of the subtract_calculator, which holds a closure. This expression evaluates to the closure itself.
  2. (10.0, 7.0) is a tuple containing the two arguments that the closure expects.
  3. The second set of parentheses (...)(...) is used to call the closure with the provided arguments.

Why the 2 sets of parentheses on this line though?

let result = (subtract_calculator.operation)(10.0, 7.0);

In Rust, you can call a closure just like you would call a regular function. However, since the closure is stored as a field in a struct, you first need to access the closure by evaluating (subtract_calculator.operation) and then immediately call it with (10.0, 7.0). This syntax allows you to invoke the closure and calculate the result.

closure in a struct
Minimal Example showing closure used in a struct

Struct with closure – example 2

Let’s give Bob a 20% pay rise using a closure that uplifts x 1.2