A brief introduction to Rust
Have you ever experienced weird behavior in your program because of an uninitialized variable or some lost pointer while writing code in C? How about performance issues in Java? Back in the day programmers had to choose between a high-performance language or a safe one. But this started to change in 2006 when a guy named Graydon Hoare started a part-time project called Rust. The idea was a fast language with high-level features. Later on, in 2009, Mozilla got involved and end up hiring Hoare. Today Rust is fighting with C and C++ as a fast and safe system language. The biggest project written in Rust so far is Servo, a high-performance browser engine created by Mozilla.
Rust is a programming language that’s focused on safety, speed, and concurrency.
The secret of Rust is a heavy process of safety checking and memory management at compile time. This provides a lot of high-level concepts with little to no performance costs.
In this article will be presented an overview of Rust syntax. But maybe what you really want to see how fast this language is. To learn more about Rust performance check a Rust vs Java benchmark and a Rust vs C. Be aware that benchmarks can not tell you how fast YOUR program will run because that relies on implementation.
Who is using Rust?
The biggest user of Rust so far is Mozzila, followed by an increasing number of companies, such as Canonical, Dropbox, npm and more. You can see a full list here: https://www.rust-lang.org/en-US/friends.html
How to get Rust?
There is a couple of ways you can get Rust. A very easy and convenient one is to get it online: https://play.rust-lang.org/.
But if you want the real deal here is how you install it on a local machine running Linux or Mac. Open a terminal and type:
I recommend a logout and login back again to set everything running. After that type the following command to check if Rust is installed:
Creating a project with Cargo
If you chose to install Rust on your machine, here is how you create a Project. Rust comes with its own build system and package-manager called Cargo. Type this on a terminal to check if you have Cargo installed:
If Cargo is installed a message with the version should appear, otherwise, an error message will be printed instead. Now let’s go ahead and create a project. Open a terminal and type the following lines:
We’ve first created a directory for Rust application, then a cargo project. The ` — bin` flag indicates out goal is to make an executable application and not a library. Libraries are very useful to integrate Rust with other languages. Open the main.rs file with your favorite text editor.
Basic syntax
Let’s write a simple “Hello, world!” program.
To run this on a local machine type this ‘cargo run’ on a terminal.
On the first line, we have a function declaration “fn main”. Just like Java and C, Rust has a main function as a way of starting applications. And them cames the line which will print information on a terminal screen: “println!”. Nothing fancy with the “println” part, but you might have noticed a weird exclamation point at the end. This is because “println!” is not a function, but a macro, which is how meta programming is done in Rust.
Variables
The declaration of variables always starts with `let`. They are strongly typed, but in a lot of cases, Rust is able to guess the type. By default, all variables in Rust are immutable. That means once set, is not possible to assign any new value to the variable.
Immutability is one of many nudges in Rust that encourages you to
write your code in a way that takes advantage of the safety and easy
concurrency that Rust offers.
But of course sometimes we need to change values and that feature is unlocked by the `mut` keyword. Maybe you will get a warning message running this code. That is because Rust does not like mutable variables if they are not necessary. When put in a for loop, for example, the message should disappear.
There is a couple of ways to perform a loop in Rust, but the intention here is to provide a quick view and highlights about Rust, so we are going to skip that.
Another way to get rid of this message is to insert an attribute above the declaration:
We will talk more about attributes later.
You may have noticed this “1_000_000” on line 3. It is possible to use underscore to facilitate number reading. “100000” and “1_000_000” are exactly the same.
Tuple
A tuple is a collection of values of different types and they can be accessed by index. They can be very useful for returning more than one value in a function.
Struct
Structs are very similar to those found in the C language. It’s a way of organizing data. First, we give a name to the group, like Person, and some fields. Very simple structure. Just like C, Rust does not have classes, but it is possible to attach a function to a struct making it very close to a class.
Something is probably bugging you out. This weird ’a things. Don’t worry about it, those are Lifetimes parameters. A Lifetime is a way Rust deals with ownership. The only way to interact with an “str” is by reference. Every time you insert a reference in your struct a Lifetime will be required to make sure the reference will live as long as the struct.
Enum
Another concept familiar to many programmers. Enum is a set of named values, but unlike Java and other languages, Enums in Rust is not mapped to just integers, instead, they are a type of data.
Enums are very flexible. It is possible to set a value or a type to any element. This can be useful when returning an error for example.
We have a new attribute here. “#[derive(Debug)]” tells Rust compiler that this particular enum can be printed out. Normally they are not made to do such a thing.
The output of this program should be:
Error Overflow(100)
Error Nullpoint
Error Other(“Generic Error”)
Notice that the name o Enum’s property is printed along with a value. Not very useful but Enums really shine when combined with a Match statement. So let’s jump into it!
Match
A Match statement is somewhat like a switch in C and Java. You can replace the Enum with a string or a number. When a default value is needed a “_” at the end of the match will do the job.
Functions
The keyword `fn` is used in functions declaration. Arguments are typed just like variables. The return value also must be informed with an arrow `->` if the function will return anything.
The last line of a function can be used as a return value without the need for the `return` keyword as you can see in the `square` function below.
Arguments
There are two kinds of argument: copy and borrowing/reference. Each kind can be mutable or immutable.
As you can see, only the “by_borrow_mut” is able to change the variable declared in the main function. By default all arguments are immutable.
Attributes
Earlier we used the “#[allow(unused_mut)]” attribute to silence a warning message from the compiler. An attribute can be used for many things. It is possible to tell the compiler a given function or module is for testing and therefore should not be in the production version with. It is also possible to enable features, establish links to external libraries and many more.
Ownership
Ownership is the main idea in Rust. This is row the language manages memory without a Garbage collector like Java or C#. The concept lives around 3 basic rules:
* Each value in Rust has a variable that’s called its owner.
* There can only be one owner at a time.
* When the owner goes out of scope, the value will be dropped.
So, everything is owned by a variable. If the owner goes way, like at the end of a function, Rust will free the memory associated with it. Ownership can be passed around, but only one variable can be the owner at a time. for example:
First, let’s take a look at integers. They are very simple, so nothing fancy happening here. x and y coexist inside the scope of the curly braces and can be used any time after been declared. Now the same example with something more complex:
If you try to use “s1” after “s2” been declared an error will occur. Objects such as string and structs are not copied at the assignment as integers. Instead what happens is a change of ownership. After the fact, “s1” does not exist anymore. That helps with memory allocation issues. If a copy is needed many objects will offer the “clone” function:
Conclusion
We’ve just scratched the surface. Rust is a system language with modern features and concepts. I hope this article has given you enough information to decide whether or not to invest in Rust to your project. To learn more deeply about Rust checkout the offitial documentation.
References
https://doc.rust-lang.org/1.22.1/book/second-edition/
https://doc.rust-lang.org/1.11.0/book/
https://stevedonovan.github.io/rust-gentle-intro/2-structs-enums-lifetimes.html
https://rustbyexample.com/fn/methods.html
https://rustbyexample.com/flow_control/match.html