Quick Note: Some Derive Traits of Rust

"Quick Note" is my blog series which I keep quick logs of what I have learned today and document it. So, it naturally does not reflect the best practice.

derive in Rust is a trait where you can apply new functionalities to structs in compile time. To give an example, let's assume we have a struct as below:

struct Person {
    name: String,
    surname: String
}

And, further in the code, we would like to print out either a Person object or a vector of Person objects. The below will fail:

let person1 = Person { name: String::from("Eray"), surname: String::from("Erdin") };
println!("{:#?}", person1);  // compilation error

Note

{:#?} is a special formatter sequence in Rust. It means to print out the inner structure of a given object in a pretty manner. You can also use {:?}, which shows the inner structure of objects compressed.

Why does it happen? Well, Rust does not see Person struct as a printable object. However, there's a workaround for that. The only thing you do is to add Debug derive trait so that Rust marks this struct as printable.

#[derive(Debug)]
struct Person {
    name: String,
    surname: String
}

When we do that, we do not get any compilation error and get a print-out for the inner structure of Person.

Are there any other useful derive traits?

Yes, there are, and they are used widely. In fact, they are used so implicitly that you almost always need to look at the source of external crates in order to have an idea about what the external structs derive.

The traits that can be used with derive can be seen in here. However, to give an example, let's check out the Eq derive trait below:

#[derive(Debug, Eq)]
struct Person {
    name: String,
    surname: String
}
// "Eq" trait creates equality check on all properties of a struct.

// later in the code...

let person1 = Person { name: String::from("John"), surname: String::from("Doe") }
let person2 = Person { name: String::from("Jane"), surname: String::from("Doe") }

if person1 == person2 {
    println!("These are the same person.");
} else {
    println!("These are not the same person.");  // this prints out
}

Can I, myself, implement how these derive traits behave?

Ah, yes, you can, but this is only a quick note and I do not think I am particularly good at Rust. I'm just a learner and this is a note to, basically, myself. However, I will not leave you clueless. This documentation gives information about how to manually implement PartialEq trait.

Basically, to implement a custom behavior for a derive trait, you need to;

  1. instead of #[derive(TheTrait)], you should impl YourStruct for TheTrait
  2. then implement the function(s) that is given in the documentation. For instance, in the documentation for PartialEq above, you should implement this signature: fn eq(&self, other: &Self) -> bool

Thanks for reading and have fun with Rust.