lundi 19 octobre 2020

To implement accessor trait over T, &T, &mut T or to define 3 differents traits?

Often, in Rust code, we find functions with name similar to as_ptr, as_mut_ptr that does the same but differs in the mutability of both there return type and the receiver type.

I am implementing a kind of trait that, for the purpose of this question, can be reduced to an accessor trait. As this accessor may be used to get a reference, a mutable reference or a value, and as there are some implementors that can provides the 3 access forms, one option I have is to provide 3 traits:

 trait Get<T> {
     fn get(self) -> T;
   }
   trait GetRef<T> {
     fn get_ref(&self) -> &T;
   }
   trait GetMut<T> {
     fn get_mut(&mut self) -> &mut T;
   }

   impl Get<i32> for Implementor {/*...*/}
   impl GetRef<i32> for Implementor {/*...*/}
   impl GetMut<i32> for Implementor {/*...*/}

I think this is the usual design pattern in Rust.

My problem with this pattern is the amplitude of the vocabulary of my crate. My opinion is that the vocabulary of my crate is too large. One of the reason is that there are also mutation/constness over a second parameter so that there are functions whose name has the form mut_get_mut, ref_get_mut, mut_get_ref, ...

In C++, where functions can be overloaded, it is common to overload for &T and &mut T. I have just figured out that with Rust we can go even further as, thanks to traits, we can overload for T, &T and &mut T:

 trait Get<T> {
     fn get(self) -> T;
   }

   impl Get<i32> for Implementor {/*...*/}
   impl<'a> Get<&'a i32> for &'a Implementor {/*...*/}
   impl<'a> Get<&'a mut i32> for &'a mut Implementor {/*...*/}

I have made few experiments, it seems to works. Hopefully, I will be able to divide the vocabulary of my crate by 3, and to turn confusing names as mut_get_ref into less confusing ones. But I am surprised not to see this pattern in other Rust code or in the standard library.

Why this last design pattern not used in Rust code? Should I continue and change my code to decrease the amplitude of my crate vocabulary or should I stick with the usual pattern involving different method name for the different receiver types?

Aucun commentaire:

Enregistrer un commentaire