My travel to the world of Rust never seem to stop amazing me.
First, there was the memory safety: no null pointers, no dangling pointers, no memory leaks. Not ever. No Garbage Collection to do that (although there is a std::gc::Gc structure for the specific use-cases where you can't run from a Garbage Collector, or std::rc::Rc if a reference counter solves your problem).
Then, there were the type system features: algebraic datatypes (disguised as Enums), linear types (owned and borrowed pointers, the things that make Rust memory-safe), tuples, struct tuples, traits, immutability by default (the way Ormagodden intended). While its type system is not as advanced as Haskell, Scala or ML (it still doesn't have higher kinded types, so I can't do something like Foo<T<U>>, or Foo<T> T<U>), it may absorb these concepts later own (higher kinded types are planned, but it's not a priority).
Then, object oriented features. They took a different approach on that: you create your structure like you would normally do (with a struct, or enum, or tuple, or tuple struct, or whatever), and then you create an "impl" block for it, where you define its methods. The impl block is also used for implement traits for your struct.
Then, functional features. There are, right now, copy closures and owned closures, besides being able to pass functions around just fine (but named functions are NOT
closures). Unboxed closures (like those of C++) still don't exist, which is somewhat limiting. But it is predicted to be implemented.
And just yesterday I discovered its module system. Holy flying fuck, it is amazing.
As a comparison, in C++ I "include" my files, and I must compile every cpp in the project together somehow. Sometimes one cpp depends on the other, sometimes they depend on some external factor. This dependency stuff gets so complex that you need Makefiles to track them. And Makefiles are complex, so lots of build tools appeared to generate Makefiles, like autotools, cmake or qmake, only to name a few. These build toolchains get quite complex overtime.
Well, Rust does not need Makefiles.
You have modules in your application. You define which modules your application will have with the "mod" keyword. And then, you import symbols from these modules with the "use" keyword. This is unlike C++, C#, Java, or most popular languages, where you can only import
modules (with #include
, using namespace, using or import), and you need to tell your build toolchain where to find them.
No, no. The mod keyword, when used (like "mod foo") will search its code either in foo/mod.rs
(not both, that will give a compiler error). You can also inline your modules, or define another path if you really want (but this convention seems just fine). And then it does its magic of including your module into your compilation. So you only need to pass one
file for the compiler, and it will inline the modules in that file (if you didn't make any mistakes, of course, like a circular dependency).
Besides that, modules can define that anything is public or private in it. You don't define that a given field of a struct is private, you define if it is private for that module
. In other words, modules provides the encapsulation usually given by the object system itself.
The "use" keyword is also quite powerful. When you use it, Rust does not only search in the global module, it can also search relatively to your current module (like self::bar for a child module, or parent::baz for another child from the parent module).
And now another catch: when you use "extern mod", it searches for libraries. Yes, you don't need Makefiles, or maven, or gradle, or anything like it at all. You can define your whole dependency tree inside your code, in a sane manner.
And all of that in a systems language
The developers must have sold their souls, it's impossible to have created such an well designed language otherwise.