Programming in Rust

Discover Rust, the systems programming language developed by Mozilla that’s fast, and wants to be better than C and C++!

Rust is a relatively new systems programming language that aims to avoid unpleasant bugs caused by unsafe code. Those of you who have experience with C or C++ will likely find the syntax of Rust quite familiar.

While Rust uses many familiar concepts from other mainstream programming languages, it also borrows elements from research languages including ‘owning pointers’ and ‘borrowed pointers’. Currently Rust is changing quite fast but still, we think the best way to learn programming with Rust is to just get hands-on and try writing some programs. All you need to get going is the Rust compiler and your favourite text editor. The Rust compiler is ingenious and able to find many errors as it’s responsible for enforcing the safety rules, preventing your Rust code from compiling until you make the necessary corrections to your code.

If after finishing this article you are hungry for more information, you will find Rust’s website (www.rust-lang.org) a good place to continue your learning. In the meantime, let’s get started with the installation!

Learn to program in Rust, Mozilla’s new language

Resources

Step-by-step

Step 01 Install Rust

As Debian 7 does not have a package ready for installation, a manual installation of Rust is required. The Rust site has precompiled binaries for most operating systems that you can download. After having extracted the Rust archive, you can then install Rust by simply running the install. sh script using root privileges.

The default installation place for the Rust compiler is the /usr/local/bin directory. The name of the compiler executable is rustc. Rust also installs another tool, called rustdoc, which is used for generating documentation from all of the Rust source files.

Step 02 Compile your first Rust program

The Rust code for the Hello World program is the following:

fn main() {
println!(“Hello World!”);
}

By convention, Rust code is saved in files that have an ‘.rs’ extension, so the “Hello World!” program can be saved as ‘hw.rs’. You can compile the hw.rs source file as follows:

$ rustc hw.rs

If you get the following error messages while trying to compile hw.rs…

error: could not exec the linker `cc`: no such file or directory
error: aborting due to previous error

… it means that you do not have a linker installed. You can solve the problem by installing the gcc package and its dependencies. If everything is okay, Rust will automatically create an executable file called ‘hw’ that you can run as usual.

Step 03 Basic language features

You can declare a new variable with the keyword let and optionally give a type to it. The compiler will then try and find out the type but if it fails, it will give you an error message. It is considered good practice to always give a type to a variable, as they are immutable by default. In order to introduce a local variable whose value you are able to change later, you should use the let mut keywords.

An identifier followed by an exclamation point, such as println!, is a macro invocation. Macros are used in Rust because they provide syntactic abstraction. You can find your version of Rust by executing the following command:

$ rustc -v

Bear in mind that Rust is currently under heavy development, so the Rust version could well be different to the one we’re using here.

Step 04 Get user input and print output

Printing output can be done with the println! macro. This macro is similar in functionality to the printf function found in C. Reading a value can be done with the help of the io::stdin().read_line().unwrap() function as follows:

It may look a little strange to begin with but you will get used to it soon enough – after all, you are learning a new programming language! The unwrap() part of the io::stdin(). read_line().unwrap() function deletes the OK value that is added in by Rust in the price variable as an indication that it was read without any problems.

Step 05 Pointers, freezing and borrowing

Rust also supports pointers – although you might be happy to learn that you don’t need to use them very often. Fully explaining pointers is beyond the scope of this article, but it’s good to know that they exist. Although Rust enforces safety while dealing with pointers, it also allows you to break this rule using an unsafe block, implying that you know what are you doing (trying to make your program run faster or because it is required by the task you are trying to implement). You can think of an unsafe block like programming in C using pointers, memory allocation and so on.

Rust also supports freezing: putting an ‘&’ in front of an object freezes it and forbids mutation – even if the object was declared as mut. ‘Frozen’ data cannot be modified via the original object, until all the references to it go out of scope. When data is borrowed, it automatically freezes. Borrowing allows you to access some data, without taking ownership over it. In Rust, resources can only have one owner, who can free or move the memory. The following code illustrates the freezing of data:

Trying to modify a frozen variable will cause the compiler to generate an error.

Step 06 Functions in Rust

Functions are declared either at the top level or inside other functions. The fn keyword introduces a function. A function has an argument list, which is a parenthesised list of ‘name: type’ pairs separated by commas. An arrow separates the argument list and the return type of the function. Every autonomous Rust program must have a main() function, as it happens in C and C++.

By default, the final expression in the function will be used as its return value, unless a semicolon terminates the expression.

Step 07 Expressions

Rust allows you to use the following unique-to-Rust syntax in order to set the value of the discount variable:

The implementation of the function that calculates Fibonacci numbers in Rust uses recursion as usual. The program accepts its input from the command line and uses various Rust features, including access to the command line arguments and vectors. The Fibonacci function is declared as follows:

fn fibonacci(n: int) -> int {...€¦

This declaration tells that the Fibonacci function takes an integer as its input and then returns an integer as its output.

The access to the vector that holds the command line arguments – skipping the first value because it’s the name of the executable – is done using the following for loop:

for x in args.iter().skip(1) {...€¦}

Step 09 Pattern matching

Rust uses the match keyword to do its pattern-matching tasks. match is similar to the switch construct found in C. You provide it with a value and a number of arms – each arm has a pattern – and the code compares the value against each pattern until it finds a match. An example is the following:

If the sqlite::open(“lud.db”) command returns Ok(a_database_name), then the code in the first arm is executed, giving the database variable the value of the db variable. Otherwise, an error message is printed (‘Cannot open lud.db!’) and the code returns. All match constructs must have arms that cover every possible case.

Step 10 Process the log files

This part of the article will present a Rust program that demonstrates how Rust deals with reading and writing of files.

Algorithmically speaking, the program will read the log file line by line, while trying to see if the current line contains the desired string and, if yes, it will write the line to a new file. Reading a text file line by line requires the following code:

Follow our to find out about all the latest Linux news, reviews, previews, interviews, features and a whole more.

MuslimAussie

Rust allows you to use the following unique-to-Rust syntax in order to set the value of the discount variable:

Really? Scala has had this syntax long before rust was ever envisioned.

Keith McNeill

Do we really need yet another language?

“Rust is a relatively new systems programming language that aims to avoid unpleasant bugs caused by unsafe code.”

Is there really no other language already filling that niche?

RogerV

Rust has compile-time protections on use of pointers (and also thread synchronization locks too) via its ownership and borrowing language intrinsic behaviors. Is basically a language that can get down to the efficiency of C while avoiding complexity of C++ and with a lot of modern characteristics as expected in 21st century programming languages. It also takes an approach to where programmer is in control of memory management choices. You have to opt into using garbage collected memory. Choose a suitable implementation library (ref counted, Mark and sweep, and/or generational) and then that is meshed with language features.