Rust: Libraries

If you’re following the Rust line of posts, you’ve read Rust: “Hello world!”. If you were paying close attention you noticed a peculiar looking function call: println!("Hello, world!");

This function call isn’t actually a function call, it is a macro. Oh, OK, wait a minute. I never defined a macro in my Hello world! code! How did it even compile?

The answer is that the Rust compiler prefixes this line to every crate root:

extern mod std;

And the compiler also inserts this line into every module body:

use std::prelude::*;

The first line essentially imports the Rust Standard Library (std) into the crate, and provides std::println!. This is analogous to #include in C++.

The second line doesn’t have any effect on the Hello world! code, but it is important to note. It re-exports many common definitions from std so that we don’t need to use global names for things like std::string::String. This is analogous to using namespace std; in C++.

Wait. What are crates and modules? All we did was generate a Hello world! program with cargo! Well, in Rust, the source code that is compiled into a binary is a crate. Modules are divisions within a crate. Further, every crate has a root module by default; you don’t declare it, it is done automatically. So our Hello world! program is organized like this:

// the crate root module begins here and contains 
// only the main function

fn main() {
    println!("Hello, world!");
}

// the crate root module ends here

A more interesting example:

// the crate root module begins here and contains 
// the main function and module foo

mod foo {
    // module foo begins here and contains two 
    // functions fooD and fooE

    fn fooD() { println!("Foodie"); }
    fn fooE() { println!("Fooey"); }

    mod bar {
        // module bar begins here and contains the 
        // function barN
    
        fn barN() { println!("Barren"); }

    }   // module bar ends here
} // module foo ends here

fn main() {
    println!("A more interesting example.");
}
// the root module ends here

Note that Rust uses // for line comments. Rust also supports C-style block comments with /**/ but the Rust style guide discourages their use.

Putting it all Together:
Say we’d like to write program that uses the tcp module from the Rust Standard Library. Our program could look something like this:

use std::io::net::tcp;

fn main() {
    let listener = tcp::TcpListener::bind("127.0.0.1:80").unwrap();
    // do net stuff

}

Rust: “Hello world!”

Rust is a multi-paradigm, applications and systems programming language. It has yet to reach 1.0 but senior C++ developers are predicting it will supersede C++ in the future.

First, download Rust from its website. Then extract the tarball, run the install script and clean up.
install

$ tar -xf rust-nightly-i686-unknown-linux-gnu.tar.gz && sudo rust-nightly-i686-unknown-linux-gnu/install.sh && rm -r rust-nightly-i686-unknown-linux-gnu/ && rm rust-nightly-i686-unknown-linux-gnu.tar.gz

Now create a Hello World! project using Rust’s package manager Cargo:

$ cargo new hello_world --bin

Take a look around in the hello_world directory. You’ll find a manifest file and a source directory. The source directory has main.rs, the generated Hello World! program.

fn main() {
    println!("Hello, world!");
}

Compile and run our Hello World! program from the hello_world directory:

$ cargo run

A similar program in C++ looks like this:

#include <iostream>

int main(void) {
	std::cout << "Hello, world!" << std::endl;
	return 0;
}

Like most Hello world! programs these are trivially different in their result. The main difference is that the main method in the Rust program is a void method while it returns an int in the C++ program. This difference could change the behavior of a non-trivial program, but for Hello world! it has no effect.