Variables and Types
Creating Variables
In Rust, you create variables with let.
fn main() {
let x = 42;
println!("{}", x); // 42
}
The {} in println! gets replaced with the variable's value.
Variables Are Immutable by Default
fn main() {
let x = 42;
x = 100; // Compile error!
}
Rust variables are immutable by default. If you want to change them, add mut:
fn main() {
let mut x = 42;
x = 100; // OK
println!("{}", x); // 100
}
Oversimplification warning: This is subtly different from "constants" in other languages, but for now just remember "you can't change it without
mut."
Numeric Types: Just Memorize These 3
Rust has tons of numeric types, but you only need these 3:
| Type | What it is | Examples |
|---|---|---|
i32 |
Regular integer | 42, -1, 0 |
usize |
Integer for array indices and lengths (0 or greater) | 0, 1, 100 |
f64 |
Decimal number | 3.14, -0.5, 1.0 |
fn main() {
let age: i32 = 25;
let index: usize = 0;
let pi: f64 = 3.14;
println!("age: {}, index: {}, pi: {}", age, index, pi);
}
Oversimplification warning: There are actually tons more like
i8,i16,i64,u8,u32,f32, etc. But we're ignoring all of them in this tutorial. We'll survive with justi32,usize, andf64.
Rust can often infer the type without you writing it:
fn main() {
let x = 42; // inferred as i32
let y = 3.14; // inferred as f64
}
You can usually omit types. Only write them when the compiler can't figure it out.
Type Conversion
You can't do arithmetic with mismatched types. Use as to convert:
fn main() {
let a: i32 = 10;
let b: f64 = 3.14;
let result = a as f64 + b;
println!("{}", result); // 13.14
let index = a as usize;
println!("{}", index); // 10
}
bool
Boolean. Either true or false.
fn main() {
let is_cool = true;
let is_boring: bool = false;
println!("{} {}", is_cool, is_boring);
}
char
A single character. Enclosed in single quotes.
fn main() {
let c = 'A';
let emoji = '🦀';
println!("{} {}", c, emoji);
}
You won't use this directly very often. You'll mostly work with strings (String).
String
There are 2 kinds of strings:
| Type | What it is |
|---|---|
&str |
String literal. Written directly in code. Fixed. |
String |
Dynamic string. Can be modified. |
fn main() {
let s1 = "hello"; // &str (string literal)
let s2 = String::from("hello"); // String
let s3 = "hello".to_string(); // This is also a String
println!("{} {} {}", s1, s2, s3);
}
Oversimplification warning: Explaining the difference between
&strandStringprecisely would take a while, so we'll skip it. When in doubt, useString::from("..."). Passing aStringwhere&stris expected usually just works.
println! Formatting
fn main() {
let name = "Rust";
let version = 2021;
// Basic
println!("Hello, {}!", name);
// Multiple values
println!("{} edition {}", name, version);
// Debug display (useful later with structs)
println!("{:?}", (1, 2, 3));
}
{} for normal display, {:?} for debug display. Debug display will come in handy in later chapters.
Variables and types are done. Next, let's learn functions and control flow.