Data and data types
Everything a program works with is data: numbers, text, true/false answers. Rust sorts data into types, and the most common ones to start with are:
| Type | Holds | Examples |
|---|---|---|
i32 | integer numbers | 3, -12 |
f64 | floating-point numbers | 3.14 |
char | a single character | 'a', 'Z', '?' |
&str | text (a string slice) | "John Doe" |
bool | true or false | true, false |
The type matters because it decides what you can do. You can do arithmetic on the number 12, but not on the text "12", which is two characters. Adding them together is a compile error: 12 + "12" reports that you cannot add &str to an integer.
What a variable is
A variable is a name attached to a value that the program keeps in memory. You can picture a box with a label: the value is in the box, and the variable name is the label. Anywhere you write the name, you get the value.
Creating a variable with let
In Rust a variable is introduced with the keyword let. The type can be written after a colon:
let name: &str;
This declares a variable named name of type &str without giving it a value yet. Rust will not let you read it until a value has been assigned. The following program does not compile:
let x: i32;
println!("{}", x);
The error says that x is "used here but it isn't initialized". For this reason, declaring a variable and giving it a value in the same statement is the normal way to write it.
Initializing a variable
The assignment operator = stores a value in the variable as it is created:
let name = "AlgoCademy";
let age = 10;
Here the types are not written. Rust works them out from the values: "AlgoCademy" is a &str, and an integer literal such as 10 becomes an i32 unless something else asks for a different integer type. This is called type inference. You can still write the type when you want to be explicit, as in let age: i32 = 10;. Both forms do the same thing.
Using a variable
Once a variable exists, you use its name to get the value, for example to print it:
let name = "AlgoCademy";
let age = 10;
println!("{}", name);
println!("{}", age);
AlgoCademy
10
A variable can also appear in a calculation: after let age = 10;, the expression age + 1 gives 11.
Variables are immutable by default
This is the biggest difference between Rust and many other languages. A variable created with plain let cannot be changed after it is given its value:
let age = 10;
age = 11;
The compiler rejects this with "cannot assign twice to immutable variable age" and suggests the fix. To allow changes, add the keyword mut:
let mut score = 10;
score += 5;
println!("{}", score);
15
Even a mutable variable keeps its type. After let mut score = 10;, the line score = "ten"; is a compile error, because a text value doesn't fit in an integer variable. Prefer plain let and add mut only when the value really has to change.
Shadowing
You can also reuse a name by writing let again. The new variable shadows the old one:
let x = 5;
let x = x + 1;
println!("{}", x);
6
This creates a new variable that happens to have the same name. It is different from mut, since a shadowing let may even change the type.
Naming and common mistakes
- Variable names use
snake_case: lowercase words joined by underscores, such asfirst_name. The compiler warns about other styles. - Strings go in double quotes and numbers don't.
let age: i32 = "31";fails with "expectedi32, found&str". - Leaving out the
;after aletstatement is a syntax error. - A declared variable that is never used triggers a warning ("unused variable"). It is only a warning, and the program still runs.
- A variable that is declared without a value can't be read until it is assigned.
The lesson's exercise
The exercise has two parts:
- Create a variable named
name, annotate its type as&str, and initialize it with"Michael". A string literal is a&str, so the types agree. - On the next line, create a variable named
age, annotate its type asi32, and initialize it with the number31. The number goes without quotes.
let name: &str = "Michael";
let age: i32 = 31;
Neither variable needs mut, since neither is changed afterwards.
Key takeaways
- A variable is a name for a value, created with
let. - Types such as
i32,f64,char,&strandbooldescribe what a value is. Rust can infer them, or you can write them after a colon. - Variables are immutable unless declared with
let mut. - Always give a variable its value when you create it.
