Be­gin Pro­gram­ming with Rust

Rust has had its begin­nings in the labs of Mozilla Re­search. This open source pro­gram­ming lan­guage is ex­tremely fast and has be­come very pop­u­lar in re­cent years.

OpenSource For You - - Contents - By: Ab­hi­nav Nath Gupta The au­thor is a soft­ware de­vel­op­ment en­gi­neer at Cleo Soft­ware In­dia Pvt Ltd, Ben­galuru, and is in­ter­ested in learn­ing pro­gram­ming tech­niques and pat­terns as well as ex­plor­ing the new and unique things that up­com­ing tech­nolo­gies hav

As de­fined by the de­vel­op­ers them­selves, Rust is a sys­tems pro­gram­ming lan­guage that runs blaz­ingly fast, pre­vents seg­faults, and guar­an­tees thread safety. Rust is spon­sored by Mozilla Re­search which de­scribes it as a safe, con­cur­rent and prac­ti­cal lan­guage.

Why learn Rust?

The goal of those who de­vel­oped Rust was for it to be a good lan­guage for cre­at­ing highly con­cur­rent and safe sys­tems. Rust is also de­signed to pro­vide speed and safety, at the same time. Due to these fea­tures, Rust has held the ti­tle of ‘Most Loved Pro­gram­ming Lan­guage’ in the Stack Over­flow De­vel­oper sur­vey for three straight years, start­ing from 2016 to 2018.

What is so unique about Rust?

Rust is in­tended to be a lan­guage for highly con­cur­rent and safe sys­tems and “pro­gram­ming in the large,” that is, cre­at­ing and main­tain­ing bound­aries that pre­serve largesys­tem in­tegrity. This has led to a fea­ture set with an em­pha­sis on safety, con­trol of mem­ory lay­out and con­cur­rency.

The per­for­mance of id­iomatic Rust is com­pa­ra­ble to the per­for­mance of id­iomatic C++. Some other unique fea­tures of Rust are:

Min­i­mal run­time

Ef­fi­cient C bind­ings

Ef­fi­cient thread han­dling with­out race con­di­tions be­tween the shared data

Guar­an­teed mem­ory safety

Type in­fer­ence

Let’s be­gin with ‘Hello World!’

In the age-old tra­di­tion of pro­gram­ming, let’s first greet the world with a ‘Hello’, i.e., a ‘Hello World’ pro­gram, as given below:

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

There is quite a lot go­ing on in these two lines of code. Let’s be­gin with fn, which is how a func­tion is de­fined in Rust. main is the en­try point of ev­ery Rust pro­gram. println! prints text to the con­sole and its ! in­di­cates that it’s a macro in­stead of a func­tion. A macro in Rust is a way to en­cap­su­late pat­terns that sim­ply can’t be done us­ing a func­tion ab­strac­tion.

Cod­ing in Rust

There are some more ways you can use the println! macro, as shown below:

fn main() { println!("{}, {}!", "Hello", "world"); // Hello, world! println!("{0}, {1}!", "Hello", "world"); // Hello, world! println!("{greet­ing}, {name}!", greet­ing="Hello", name="world"); // Hello, world!

println!("{:?}", [1,2,3]); // [1, 2, 3] println!("{:#?}", [1,2,3]);

/* [

1, 2, 3 ] */

// for­mat! macro is used to store the for­mat­ted STRING let x = for­mat!("{}, {}!", "Hello", "world"); println!("{}", x); // Hello, world! }

Data types in Rust

A few ba­sic data types in Rust are: bool: To de­fine true or false val­ues char: A sin­gle char­ac­ter value

Fixed size (bit) signed (+/-) in­te­ger types: Denoted as i8, i16, i32, i64 where the num­ber af­ter i rep­re­sents the bit size

Fixed size (bit) un­signed (+) in­te­ger types: Denoted as u8, u16, u32, u64 where the num­ber af­ter u rep­re­sents the bit size

Vari­able sized signed (+/-) in­te­ger: Rep­re­sented as isize in code. Cov­ers all signed in­te­ger types

Vari­able sized un­signed(+) in­te­ger: Rep­re­sented as usize in code. Cov­ers all un­signed in­te­ger types

32-bit float­ing point: Rep­re­sented as f32 in code

64-bit float­ing point: Rep­re­sented as f64 in code

Ar­rays: Fixed size list of el­e­ments of the same data type. Ar­rays are im­mutable by de­fault and even with mut, their el­e­ment count can­not be changed

Tu­ples: Fixed size or­dered list of el­e­ments of dif­fer­ent (or the same) data types. Tu­ples are also im­mutable by de­fault and even with mut, their el­e­ment count can­not be changed. Also, if you want to change an el­e­ment’s value, the new value should have the same data type of the pre­vi­ous value

Slice: Used to cre­ate a ref­er­ence to only part of an­other data struc­ture

Str: Un­sized UTF-8 se­quence of Uni­code string slices Ex­am­ples of the above data types are shown below:

let a : bool = true; // bool type let x = ‘x’; // char type let num: i16 = 12 // fixed size signed in­te­ger type let unum: u16 = 13 // fixed size un-signed in­te­ger type let a = [1, 2, 3]; // a[0] = 1, a[1] = 2, a[2] = 3 // ar­ray type let a = (1, 1.5, true, ‘a’, “Hello, world!”); // tu­ple type

// ex­am­ple of slice let a: [i32; 4] = [1, 2, 3, 4];//Par­ent Ar­ray

let b: &[i32] = &a; //Slic­ing whole ar­ray let c = &a[0..4]; // From 0th po­si­tion to 4th(ex­clud­ing) let d = &a[..]; //Slic­ing whole ar­ray

// ex­am­ple of Str datatype let a = “Hello, world.”; //a: &’static str

Vari­able bind­ings, con­stants and stat­ics in Rust

In the do­main of Rust, the vari­ables are im­mutable by de­fault; hence, they are called vari­able bind­ings. To make them mu­ta­ble, the mut key­word has been used. Rust is a stat­i­cally typed lan­guage, but it doesn’t need to de­fine the data type while declar­ing a vari­able bind­ing. The com­piler is smart enough to fig­ure out the best data type af­ter check­ing the us­age. The only ex­cep­tion to this rule is when you de­clare the con­stants and static vari­ables. While declar­ing con­stants and stat­ics, you must de­clare the type us­ing a colon (:). Types come af­ter the colon.

Ex­am­ples for vari­able bind­ings are given below: let a = true; // with­out spe­cific dec­la­ra­tion of type let b: bool = true; // with spe­cific dec­la­ra­tion of type let mut z = 5; // mu­ta­ble vari­able bind­ing

The let key­word is used in bind­ing ex­pres­sions. We can bind a name to a value or a func­tion.

An ex­am­ple of con­stants is shown below:

const con­st_1: i32 = 5;

The const key­word is used to de­fine con­stants. An ex­am­ple of stat­ics is given below:

static stat­ic_1: bool = true;

The static key­word is used to de­fine the ‘global vari­able’ type fa­cil­ity.

One note­wor­thy dif­fer­ence be­tween static and const is that the for­mer has a fixed lo­ca­tion in mem­ory while const doesn’t.

Func­tions in Rust

Func­tions are de­clared with the key­word fn. An ex­am­ple of a func­tion in Rust is given below:

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

When pass­ing ar­gu­ments to a func­tion, it is im­per­a­tive that the data types of the ar­gu­ments are de­clared, as shown in the ex­am­ple below:

fn print­_­sum_of_num­bers(num1: i8, num2: i8) -> i32 { println!(“ad­di­tion is: {}”, num1 + num2); num1+ num2 //no ; means an ex­pres­sion, re­turn num1+num2 }

In Line 1 of the above snip­pet, ->i32 de­ter­mines the re­turn type of the value re­turned by the func­tion print­_­sum.

In Rust, the func­tion body can be as­signed to a vari­able, de­scribed as func­tion point­ers, as shown in the snip­pet below:

// Func­tion point­ers fn point­erEx­am­ple(count: i32) -> i32 {

count + 1 //no ; means an ex­pres­sion, re­turn count +1 }

let count1= point­erEx­am­ple; let count2 = count1(5); //6

Con­trol flows in Rust

A wide ar­ray of con­trol flows is avail­able in Rust, in­clud­ing pop­u­lar ones like if-else, for and while loops, as well as some con­trol flows ex­clu­sive to Rust, i.e., match and loop. An ex­am­ple of these is shown in the code snip­pet below:

// if-else Ex­am­ple let com­p_­size = 7; if comp _size < 5 {

println!(“Small Com­pany”); } else if comp _size < 10 {

println!(“Medium Com­pany”); } else {

println!(“Large Com­pany”); } // while loop ex­am­ple

let mut count= 0; while count < 5 { if count == 0 { println!(“Omit value : {}”, b count count += 1; con­tinue;

} else if count == 2 { println!(“exit At : {}”, count); break; } println!(“value : {}”, count); count += 1; }

// for Loop Ex­am­ple for count in 0..10 { if count == 0 { println!(“Omit Value : {}”, count); con­tinue;

} else if count == 2 { println!(“Exit At : {}”, count); break;

} println!(“value : {}”, count);


An­other unique con­trol flow avail­able in Rust is loop, which is used to in­di­cate an in­fi­nite loop, out-of-the-box. The break state­ment can be used to exit a loop at any time, whereas the con­tinue state­ment can be used to skip the rest of the it­er­a­tion and start a new one, as shown in the code snip­pet below:

fn main() { let mut count = 0u32;

println!(“Let’s count un­til in­fin­ity!”);

// In­fi­nite loop loop {

count += 1;

if count == 3 { println!(“three”);

// Skip the rest of this it­er­a­tion con­tinue; } println!(“{}”, count);

if count == 5 { println!(“OK, that’s enough”);

// Exit this loop break; } } }

Last but not the least, let us dis­cuss ‘match’. Rust pro­vides pat­tern match­ing through the match key­word, which can be used in switch state­ments in C. An ex­am­ple of match is shown in the snip­pet below:

fn main() { let num­ber = 13;

// TODO ^ Try dif­fer­ent val­ues for `num­ber`

println!(“Tell me about {}”, num­ber); match num­ber {

// Match a sin­gle value

1 => println!(“One!”),

// Match sev­eral val­ues

2 | 3 | 5 | 7 | 11 => println!(“This is a prime”), // Match an in­clu­sive range

13...19 => println!(“A teen”),

// Han­dle the rest of cases

_ => println!(“Ain’t spe­cial”), }

let boolean = true;

// Match is an ex­pres­sion too let bi­nary = match boolean {

// The arms of a match must cover all the pos­si­ble val­ues

false => 0, true => 1,

// TODO ^ Try com­ment­ing out one of these arms }; println!(“{} -> {}”, boolean, bi­nary); }

This con­cludes our ex­plo­ration of the ba­sics of the Rust pro­gram­ming lan­guage. Rust has many more unique fea­tures to of­fer, like cus­tom macros, which are be­yond the scope of this ar­ti­cle. To get more de­tails about these, of­fi­cial Rust doc­u­men­ta­tion can be re­ferred to.


[1]­gram­ming_lan­guage) [2] [3] https://in­sights.stack­over­­vey/2016#tech­nol­ogy [4] https://in­sights.stack­over­­vey/2017#tech­nol­ogy [5] https://in­sights.stack­over­­vey/2018#tech­nol­ogy [6] https://learn­ing-rust.git­

Newspapers in English

Newspapers from India

© PressReader. All rights reserved.