Behavior Protocols in Rust

I'm just starting out with Rust and so far, there is a lot of good stuff I like about the language and especially its type system. I do have a bit of a background in type system and, currently, considering Rust as a contender to port some highly specialized Swift code.

One of the key aspects about Swift is the concept of Protocols over generics, which essentially defines a set of fields that must be specialized and a set of methods that must be implemented whenever applying a protocol. The concept is well documented.

https://docs.swift.org/swift-book/LanguageGuide/Protocols.html

I used Swift and especially in a project to build a proof of concept leaning heavily on protocols, which worked and got the job done. However, the PoC isn't portable to Golang, the main language of the project, due to the lack of generics in Golang and overall a fairly basic type system.

For a number of reason, Swift became dead on arrival and must be replaced. Go isn't doing the trick either, but because the actual delivery is a standard microservice communicating over a binary protocol, I am free to bring in any language that can replace the Swift code base.

Rust seems to tick off a lot of important requirements:

  • Generics
  • Traits
  • Type hierarchy
  • Nice compiler
  • Higher order functions and a lot more of the good FP stuff.

The goal is to define a collection of type T and then attach a custom set of methods only applicable to collections of type T and these collection methods actually call functions attached to items of type T.

In Swift, I can write a protocol that essentially extends an existing type to add new functionality.
Say, I have collection of type T and I extend that collection with a function called Thinking(). The Swift compiler then attaches that function to any collection of Type T.

In Rust, I believe there a roughly two ways:

  1. Struct with a type parameter and then attach methods to that type. If I am not mistaken, this way a generic type parameter can only be substituted with one concrete type at a time.

  2. Struct with a type parameter that implements a trait over the same type parameter. That way, trait objects allow for multiple concrete types to fill in for the trait object at runtime. The docs give this example:

pub struct Screen<T: Draw> {
    pub components: Vec<T>,
}

impl<T> Screen<T>
where
    T: Draw,
{
    pub fn run(&self) **strong text**

The big question I have is this:

Do I need to define my custom type & trait over a custom collection OR can I actually extend the standard collections with some methods over a type T applicable only to collections of type T?

In Go, I have to do the first approach with a lot code duplication due to the lack of generics. In swift, I do the second approach in a much more concise way thanks to protocols that extent standard collections over custom type.

Where exactly is Rust positioned given those two extremes?

And again, I am just starting out with Rust so please bear with my limited understanding of Rust concepts. Thank you for any help understanding this further.

You can do that without defining a new collection, by creating a trait.

For example:

trait<T: Draw> Runnable {
    fn draw(&self);
}

impl<T: Draw> Runnable<T> for Vec<T> {
    fn draw(&self) { /* ... */ }
}

BTW, If all you need is immutable access to the collection then it's more useful to impl Trait for [T].

Note however that the trait need to be in scope (used) in order to reference its method with the dot syntax (vec.run()). You can always use the explicit call syntax (Runnable::run(&vec) or even <Vec<T> as Runnable<T>>::run(&vec)).

1 Like

It sounds like you are talking about the Extension Trait pattern.

This lets you attach new methods to something which satisfies certain behaviours (e.g. an existing trait).

1 Like

Brilliant, thank you so much.

Yes, extension trait exactly what I'm looking for. You made my day!

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.