Simplify Rust Code with Easy Elegance: Unleashing the Power of Fluent Interfaces

Photo by Pixabay: https://www.pexels.com/photo/abstract-active-ash-color-235807/

Introduction

Using a fluent interface can make your code easier to understand. This pattern allows you to link method calls, where each method returns the object or context. When implemented well, it creates a specialized language for a specific domain.

Let’s explore how this works in Rust.

Implementation in Rust

For this example we will implement a simple fluent interface on an Address-struct:

#[derive(Debug)]
struct Address {
    street: String,
    number: u32,
    city: String,
    country: String,
}

Now we need to implement some methods:

impl Address {
    fn new() -> Self {
        Address {
            street: String::new(),
            number: 0,
            city: String::new(),
            country: String::new(),
        }
    }

    fn street(&mut self, street: &str) -> &mut Self {
        self.street = street.to_string();
        self
    }

    fn number(&mut self, number: u32) -> &mut Self {
        self.number = number;
        self
    }

    fn city(&mut self, city: &str) -> &mut Self {
        self.city = city.to_string();
        self
    }

    fn country(&mut self, country: &str) -> &mut Self {
        self.country = country.to_string();
        self
    }
}

Some notes:

  1. The constructor, the new() method creates an empty Address struct.
  2. The street() method is passed a mutable reference to self, and also return a mutable reference to Self
  3. In that method we set the appropiate field and return self. Remember that returning a value in Rust can be done by putting the value on a separate line without a semicolon.

As you can see, implementing a fluent interface this way is not very complicated.

Testing

Now we can test to see if our setup works:

fn main() {
    let mut address=Address::new();
    address
        .street("Middle Road")
        .number(50)
        .city("Arcadia")
        .country("Utopia");

    println!("{:?}", address);
}

We create an address, set its field, and then print it.

Conclusion

The fluent interface can make your code more readable and flexible, however, it might not always be the right choice for every situation. As always one must consider the trade-offs, since it might improve readability in our example, this might not always be the case, and it might even increase complexity for example in the form of unwieldy chains of method calls. Always assess whether it suits the specific needs of your code.

Leave a Reply

Your email address will not be published. Required fields are marked *