Rust - First Steps
I was interested in Rust quite a while but never found spare time to experiment with it. Also, recently I found https://www.redox-os.org/ - an OS with Rust based microkernel. I always thought that it would be nice to customize the OS kernel. But Linux being a monolithic kernel and written in C sounds like a lot of work to do any changes. So, in order to play with Redox I have to know some Rust :)
Hello World
As usual the very first code I wrote was a hello world application:
This reminds me a lot of C: main entry point is called main, double quoted strings and semicolon after the statement.
Variables
In Rust variables are immutable (const in C++) by default:
Mutable variables are marked explicitly:
Rust uses static typing system but you don't necessarily have to specify the variable type:
Compiler infers the variable type just like C++ and Swift does.
Strings
String operations are very common in every language. So good string support can make developer's life a lot easier.
Rust has two string types: &str and String. String handles UTF-8 I was suprised to see that symbol indexing does not work with String:
And this makes sense: it's not so easy to index UTF-8 strings, because each symbol has a variable length of bytes. Thus accessing UTF-8 string character at position x has O(n) complexity. Usually, when we are indexing an array we expect O(1) operation. So we're better off accessing characters explicitly:
Rust has a bytes literal identical to Python
Functions
Rust function definitions remind me of Swift ones or Python type hints.
In Rust almost everything is an expression. Just like in Ruby. So return statement might be omitted:
Lambda functions are called closures in Rust. Their syntax reminds me of Ruby:
Optional
Rust has optional types <https://doc.rust-lang.org/std/option/>_ which represent variables that might not have any value. They seem similar to Swift's optionals:
fn div(a: f64, b: f64) -> Option<f64> { if b == 0.0 { None } else { Some(a / b) } } println!("{}", div(10.0, 2.0).unwrap());
Also, in case of None I can specify default value:
Dependency Manager
Rust has a dependency manager, Cargo, which is also a build system. First of all, this is super cool, because C and C++ doesn't have a widely adopted dependency manager. Except a couple attempts to implement one:
Also, C and C++ have so many build systems that it's easy to get lost:
And recently I just found out that Google is building another one - Bazel. Which they are using to build Tensorflow...
From time to time I see those used actively, not just listed in Wikipedia.
I like the Zen of Python:
There should be one-- and preferably only one --obvious way to do it.
And regarding build tools in C, C++ world, this is not the case :/ So although I used Cargo only for two days, I loved the way it works.
Compiler
rustc - initially implemented in OCaml, later rewritten in Rust itself. It has some nice features that caught my eye. It has plugin system: https://doc.rust-lang.org/book/compiler-plugins.html, which allows us to extend the compilers behavior like manipulate the AST, etc.
Another feature I find really attractive is attributes. They allow to annotate/label definitions. E.g. there is an attribute that labels function as a test:
Then cargo finds those labelled functions and execute them simply running:
$ cargo test
Also, attributes can be used to select which code to compile for specific platform. Compare:
#[cfg(target_os = "linux")] fn do_stuff() { println!("You are running linux!") } #[cfg(target_os = "windows")] fn do_stuff() { println!("You are running windows!") }
with C++ implementation:
Comments