Dumindu Madunuwan
Learning Rust
Published in
12 min readJan 24, 2016

--

“A language that doesn’t affect the way you think about programming, is not worth knowing.”
__ Alan Perlis

RUST BASICS

This is the first post of Learning Rust series. Also now, you can read the same content via learning-rust.github.io 👈 . I think it’s more structured and easy to see the big picture.

Why Rust?

Things started in 2007–2009, in my final years at the university. I chose a web based project for the final year project submissions, while my friends chosen Java Native Application projects. And that is how I became a web developer.

I chose web because at that time I truly believed, web will be the next Ultimate, System Independent & Language Independent platform and the next generation software ecosystem will be implemented top of browsers. The web I expected is sort of similar to this.

But things were changed because of Apple. This is how it tells in Wikipedia.

In 2007, Apple Computer launched the iPhone1.0 the company’s first ever smartphone. When the device launched, the device did not provide any support for third-party software: Apple’s CEO Steve Jobs believed that web apps served over the internet could provide adequate functionality required for most users. Soon after its release, however, developers had managed to “jailbreak” the iPhone and begin coding third-party apps for the device, distributed through package managers such as Installer.app (which itself was based on APT) and Cydia. With the release of iPhone OS 2.0 in July 2008, Apple launched the App Store; officially introducing third-party app development and distribution to the platform.

Android copied Apple. Both created new ways to generate extra revenue via their Closed Mobile App Ecosystems. They provided better ways to write native apps instead of web apps. But we had a hope with Facebook.

Web apps were centered around Facebook. Also Facebook chose HTML5 to build their mobile apps. When Rockmelt came, I was thrilled. If Facebook acquired Rockmelt and officially announced it via Facebook, It could be next the Chrome OS. But Mark Zuckerberg didn’t think that way. Smartphone user base was grown rapidly. HTML5 couldn’t compete with native apps in the closed mobile ecosystems of Apple and Google. Facebook ditches HTML5.

“The biggest mistake we made as a company was betting too much on HTML5 as opposed to native”
__ Mark Zuckerberg

OK, back to my story. I’m a PHP developer but past 3–4 years I was more concerned about HTML5, CSS3, RWD, UI/UX because I also bet on HTML5 over native apps. It’s true that web technologies are slowly adapting for native app development via asmjs, NativeScript, Electron, WebAssembly, React Native but future web application development will be more complex because of Emerging Connected Cars and VR Ecosystems.

On the other hand C++, Go like programming languages are adapting for web development to build performant web apps and PHP is becoming a dying language. So learning a systems programming language is much wiser in these days. We have many trending languages like JavaScript, Julia, Go, Rust, Swift but explaining the pros and cons of each language is beyond the purpose of this article. I chose Rust and it caught my interest at the first sight.

is Rust worth knowing ?

http://thoughtram.io/rust-and-nickel/#/11

Rust is a systems programming language which focused on safety, speed, and concurrency at the same time. It’s a very low level language and it doesn’t use Garbage Collection(GC) by default.

🔎 One of Rust’s most unique and compelling features is Ownership, which uses to achieves memory safety. Rust creates memory pointers optimistically, checks memory pointers’ limited accesses at the compiler time with the usage of References and Borrowing. And it does automatic compile time memory management by checking the Lifetimes. 🔥 Refer RUST : THE TOUGH PART

Rust is a very modern language. It uses LLVM on its backend. Rust supports a mixture of imperative procedural, concurrent actor, object-oriented and pure functional styles. It also supports generic programming and metaprogramming, in both static and dynamic styles.

📖 By the way Rust is not a particularly original language. Its design elements came from a wide range of sources.
▸ Abstract Machine Model : C
▸ Data types : C, SML, OCaml, Lisp, Limbo
▸ Optional Bindings : Swift
▸ Hygienic Macros : Scheme
▸ Functional Programming : Haskell, OCaml, F#
▸ Attributes : ECMA-335
▸ Memory Model and Memory Management : C++, ML Kit, Cyclone
▸ Type Classes : Haskell
▸ Crate : Assembly in the ECMA-335 CLI model
▸ Channels and Concurrency : Newsqueak, Alef, Limbo
▸ Message passing and Thread failure : Erlang

and etc.

It’s low level, safe, modern and feature rich. So it’s suitable for any type of software development. Other than that it’s a properly designed language. So you will be able to learn/practice new programming paradigms with Rust. Hope you got excited. OK, let’s start.

Installation

There are many ways to install Rust on your system. For the moment the official way to install Rust is using Rustup.

⭐️ If you are on Microsoft Windows, you have to install Visual C++ Build Tools 2013 or higher. The recommended way is installing Visual C++ 2015 Build Tools which requires additional 3–4 GBs.

📖 Rustup installs The Rust Programming Language from the official release channels, enabling you to easily switch between stable, beta, and nightly compilers and keep them updated. It makes cross-compiling simpler with binary builds of the standard library for common platforms.

📖 Rustup installs rustc, cargo, rustup and other standard tools to Cargo's bin directory. On Unix it is located at $HOME/.cargo/bin and on Windows at %USERPROFILE%\.cargo\bin. This is the same directory that cargo install will install Rust programs and Cargo plugins.

💡 More information can be found on the Github page of Rustup project.

After installing Rust you can check the current version by typing rustc --version or rustc -V on your terminal to verify the success of the installation.

Hello World

fn means function. main function is the beginning of every Rust program. println! prints text to the console and its ! indicate that it’s a macro instead of a function.

💡 Rust files should have .rs file extension and if you’re using more than one word for the file name, follow the snake_case.

▸ Save the above code in file.rs , but it can be any name with .rs extension.
▸ Compiling via rustc file.rs
▸ Executing by ./file on Linux and Mac or file.exe on Windows

💯 These are the other usages of println! macro,

Cargo, Crates and Basic Project Structure

Cargo is Rust’s built-in package manager and the build system.

It can be used to,
▸ Create a new project: cargo new
▸ Build the project: cargo build
▸ Run the project: cargo run
▸ Update project dependencies: cargo update
▸ Run tests: cargo test
▸ Generate the project documentation via rustdoc: cargo doc
▸ Analyze the project to see it has any errors, without building it: cargo check

In addition, there are cargo commands to publish the project as a crate/ package to Rust’s official crate registry, crates.io.
▸ Log in to crates.io with the API token: cargo login
▸ Make the local crate uploadable to crates.io: cargo package
▸ Upload the crate to crates.io: cargo publish

⭐️ A crate is a package. Crates can be shared via Cargo.

A crate can produce an executable or a library. In other words, it can be a binary crate or a library crate.
01. cargo new crate_name --bin OR cargo new crate_name: produces an executable
02. cargo new crate_name --lib : produces a library

The first one generates,

and the second one generates,

  • Cargo.toml(capital c) is the configuration file which contains all of the metadata that Cargo needs to compile your project.
  • src folder is the place to store the source code.
  • Each crate has an implicit crate root/ entry point. main.rs is the crate root for a binary crate and lib.rs is the crate root for a library crate.

💡 When we build a binary crate via cargo build or cargo run, the executable file will be stored in target/debug/ folder. But when build it via cargo build --release for a release it will be stored in target/release/ folder.

This is how Cargo Docs describes about the recommended Project Layout,

▸ Source code goes in the src directory.
▸ The default library file is src/lib.rs.
▸ The default executable file is src/main.rs.
▸ Other executables can be placed in src/bin/*.rs.
▸ Integration tests go in the tests directory (unit tests go in each file they're testing).
▸ Examples go in the examples directory.
▸ Benchmarks go in the benches directory.

Comments and Documenting the code

Nested block comments are supported.

💡 Always avoid block comments, Use line comments instead.

Doc comments support Markdown notations. Using cargo doc, the HTML documentation can be generated from these doc comments. Let’s see the difference between the two sets of doc comments.

As you can see both use to document the same module. First comment has been added before the module while the second one has been added inside the module.

💡 Only use //! to write crate and module-level documentation, nothing else. When using mod blocks, use /// outside of the block.

Also we can use doc attributes for documenting the code.
💡 An attribute is a general, free-form metadatum that is interpreted according to name, convention, and language and compiler version. Any item declaration may have an attribute applied to it.
In here each comments are equivalent to relevant data attributes.

Variable bindings , Constants & Statics

⭐️ In Rust variable are immutable by default, so we call them Variable bindings. To make them mutable, mut keyword is used.

⭐️ Rust is a statically typed language; It checks data type at compile time. But it doesn’t require you to actually type it when declare variable bindings. On that case compiler checks the usage and set a better data type for it. But for constants and statics you must annotate the type. Types come after a colon(:)

  • Variable bindings
  • Constants
  • Statics

let keyword is used in binding expressions. We can bind a name to a value or a function. Also because of left-hand side of a let expression is a ‘pattern’, you can bind multiple names to set of values or function values.

const keyword is used to define constants. It lives for the entire lifetime of a program but have no fixed address in memory. static keyword is used to define ‘global variable’ type facility. There is only one instance for each value, and it’s at a fixed location in memory.

💡 Always use const, instead of static. It’s pretty rare that you actually want a memory location associated with your constant, and using a const allows for optimizations like constant propagation not only in your crate but also in downstream crates.

💡 Usually statics are placed at top of the code file, outside the functions.

Functions

▸ Functions are declared with the keyword fn
▸ When using arguments, you must declare data types.
▸ By default functions return empty tuple (). If you want to return a value, return type must be specified after ->

Primitive Data Types

  • bool : true or false
  • char : a single Unicode scalar value
  • i8, i16, i32, i64, i128 : fixed size(bit) signed(+/-) integer types

💡 Min and max values are based on IEEE standard for Binary Floating-Point Arithmetic; From -2ⁿ⁻¹ to 2ⁿ⁻¹-1 . You can use min_value() and max_value() to find min and max of each integer type, ex. i8::min_value();

  • u8, u16, u32, u64, u128 : fixed size(bit) unsigned(+) integer types

💡 Same as signed numbers, min and max values are based on IEEE standard for Binary Floating-Point Arithmetic; From 0 to 2ⁿ-1 . Same way you can use min_value() and max_value() to find min and max of each integer type, ex. u8::max_value();

  • isize, usize : pointer sized signed and unsigned integer types
    The actual bit size depends on the computer architecture you are compiling your program for. By default, the sizes are equal to 32 bit on 32-bit platforms and 64 bit on 64-bit platforms.

🔎 Search more about cross-compiling and Supported Tiers of Rust programs.

  • f32 : 32-bit floating point
    Similar to float in other languages, Single precision. Should avoid using this unless you need to reduce memory consumption badly or if you are doing low-level optimization, when targeted hardware not supports for double-precision or when single-precision is faster than double-precision on it.
  • f64 : 64-bit floating point
    Similar to double in other languages, Double precision.
  • arrays : fixed-size list of elements of same data type

⭐️ Arrays are immutable by default and also even with mut, its element count can not be changed.

🔎 If you are looking for a dynamic/ growable array, you can use Vec. Vectors can contain any type of elements but all elements must be in the same data type.

  • tuples : fixed-size ordered list of elements of different(or same) data types

⭐️ Tuples are also immutable by default and even with mut, its element count can not be changed. Also if you want to change an element’s value, new value should have the same data type of previous value.

  • slice : dynamically-sized reference to another data structure
    Think you want to get/pass a part of an array or any other data structure. Instead of copy it to another array (or same data structure), Rust allows to create a view/reference to access only that part of data. And it can be mutable or not.
  • str : unsized UTF-8 sequence of Unicode string slices

⭐️ str is an immutable/statically allocated slice holding an unknown sized sequence of UTF-8 code points stored in somewhere in memory. &str can be used to borrow and assign the whole array to the given variable binding.

🔎 A String is a heap-allocated string. This string is growable, and is also guaranteed to be UTF-8. They are commonly created by converting from a string slice using the to_string() and String::from() methods.
ex: “Hello”.to_string();
String::from(“Hello”);

💡 In general, you should use String when you need ownership, and &str when you just need to borrow a string.

  • functions
    As we discussed on above functions section, b is a function pointer, to plus_one function

Operators

  • Arithmetic Operators : + - * / %

🔎 Also + is used for array and string concatenation

  • Comparison Operators : == != < > <= >=
  • Logical Operators : ! && ||

🔎 On integer types, ! inverts the individual bits in the two’s complement representation of the value.

  • Bitwise Operators : & | ^ << >>
  • Assignment and Compound Assignment Operators
    The = operator is used to assign a name to a value or a function. Compound Assignment Operators are created by composing one of + - * / % & | ^ << >> operators with = operator.
  • Type Casting Operator : as

Control Flows

  • if - else if - else

⭐️ Return data type should be same on each block, when using this as an expression.

  • match
  • while
  • loop
  • for

OK, Let’s stop the first post of Learning Rust (& Gitbook)series in here. In this post I just tried to summarize about the very basics of Rust .

▸ Installation & Hello World ▸ Cargo & Crates ▸ Variable bindings , Constants & Statics ▸ Comments ▸ Functions ▸ Primitive Data Types
▸ Operators ▸ Control Flows

🐣 As you know, I am not an expert in Rust. I’m a Web Developer who is just learning Rust. So if you found any mistake or something I need to change, even a spelling or a grammar mistake, please let me know. Thanks.

🎓 For more information you can go through,
▸ Rust Documentation First edition & Second edition
The Rust Reference & Rust Syntax Index
Rust by Example
Rust Programming Course of University of Pennsylvania 🎖

👥 To get a help,
The Rust Community & #rust-beginners IRC 🎖
Sub-Reddit, /r/rust

📚 Books
Programming Rust 🎖
Rust Essentials

“Every great wizard in history has started out as nothing more than what we are now, students. If they can do it, why not us?”

__ J.K. Rowling (Harry Potter and the Order of the Phoenix)

NEXT ▸ Vectors ▸ Structs ▸ Enums ▸ Generics ▸ Impls & Traits

--

--

Dumindu Madunuwan
Learning Rust

I am a web developer and a designer who loves Rust, Golang, Firefox, UI/UX, Linux and Gnome.