[rust-dev] C++ to Rust - Is that about right?

Christoph Husse thesaint1987 at googlemail.com
Mon Jul 14 11:45:20 PDT 2014


Hi,

I am just starting to think I have wrapped my mind around this type
system shift introduced by rust. Now I just want to confirm that view
to make sure I haven't missed something important.

Declaring a C++ class in rust:

#########################

// MyMod/mod.rs - One monolythic file of all structs, enums and traits
my "logical module" wants to define

struct MyClass {
   // all member variables go here
}

trait IMyClass {
    // all functions (any "new" functions that is) go here
}

// MyMod/MyClass/mod.rs - Constructors and direct functions go here

mod ISomeTrait;

impl IMyClass for MyClass {
    // My implementations go here
}

impl MyClass {
    // My constructors go here

    pub fn new() -> Box<IMyClass> {
        box MyClass{} as Box<IMyClass>
    }
}

// MyMod/MyClass/ISomeTrait.rs - Implementation of "ISomeTrait" for
"MyClass" goes here

impl ISomeTrait for MyClass {
    // My implementation goes here
}

#########################

Now I can hear the screams already :D. So I want to explain a bit
about this choice.

First, I find the rust source code I looked at so far pretty
unstructured and confusing. Everything seems to be defined somewhere
at will, without having a real concept (or I am just blind to see it).

I think it is annoying to put exported types into submodules, because
this will create a "use" nightmare. It is equally annoying to have
those huge files as many rust projects have atm, by defining AND
implementing various types in the same module.

So my take on this is:

1) Use the "mod.rs" file to define all traits, enums and structs your
module exports. This gives a clean and documented overview of what
your modules exports, like an index... Or a previous C++ header file
usually did.

2) Create subdirectories (if necessary) for each trait/struct defined
in your modules, where you can distribute your implementations in a
structured manner (like shown above). Since implementations are always
imported (thank god) the user of your module doesn't need to create
convoluted "use" paths to all spagetti parts of your submodule
nightmare... And readers of your module can easily find what they are
looking for too.

3) The "interface" naming makes most sense to me because right now I
think that's what traits seem to be. Its a way of implementing an
interface for classes or other interfaces that you do not control.
Basically you are able to inject new functionality into existing types
without having source code access to them. Which is great and reminds
me a lot of C#'s extension methods, only that the RUST way seems much
better...

Right now the biggest issue for me is getting structure into a bigger
rust project. Small clean files that do only few things (I don't want
to have files bigger than a few hundred lines at MAX). But I don't
want to have a "use" nightmare either. A "package" like in Java should
be consumed by "use path.to.package.SomeType" which is already verbose
enough. But for Rust this seems to mean that I have to put all my
types into one file, which isn't exactly what I want...

Maybe a lot of this is implicitly covered by the tutorial but for all
of us who come from languages like Java, C++ and C#, I think its hard
to really wrap around this "new" concept.

Any comments ;)?
Thanks


More information about the Rust-dev mailing list