Types without ceremony
Worked examples
Read the claim, then run it and check the machine agrees. One at a time — nothing here is taken on trust.
fn main() {
let answer = 42; // i32 by default
let ratio = 2.5; // f64 by default
println!("answer = {answer}, ratio = {ratio}");
println!("7 / 2 = {}", 7 / 2); // integer division: 3
println!("7.0/2.0 = {}", 7.0 / 2.0); // float division: 3.5
// inference runs backwards, too: this literal MUST be u8
let byte: u8 = 200;
println!("byte = {byte}, u8::MAX = {}", u8::MAX);
}
Prints 3 then 3.5 — the operands' types pick the division, and
an all-integer expression truncates. The byte line shows
inference flowing from the annotation into the literal: 200 is
born a u8 because the binding demands it. Change it to 300 and
rustc rejects the program at compile time — 300 doesn't fit in a
u8 and the compiler knows it.
fn main() {
let point: (i32, f64, char) = (3, 2.5, 'x');
println!("x = {}, weight = {}, tag = {}", point.0, point.1, point.2);
let arr = [10, 20, 30];
println!("len {}, first {}, last {}", arr.len(), arr[0], arr[2]);
// arr[5] would compile-error here (constant index, known len);
// with a runtime index it PANICS: "index out of bounds: the
// len is 3 but the index is 5". The polite alternative:
println!("arr.get(0) = {:?}", arr.get(0));
println!("arr.get(5) = {:?}", arr.get(5));
}
.get(i) returns Some(&value) in bounds and None out of
bounds — printed: Some(10) and None. It's the same
answer-or-no-answer shape as checked_add, and you'll meet it
everywhere: Rust APIs return the possibility of absence as a
VALUE instead of crashing or handing you garbage memory.
fn main() {
println!("i32 range: {} ..= {}", i32::MIN, i32::MAX);
println!("checked: {:?}", i32::MAX.checked_add(1));
println!("checked ok: {:?}", 40i32.checked_add(2));
println!("wrapping: {}", i32::MAX.wrapping_add(1));
println!("saturating: {}", i32::MAX.saturating_add(1));
// unsigned subtraction below zero is overflow too:
println!("3u32 - 5? {:?}", 3u32.checked_sub(5));
// wrapping is a feature when the domain really is a cycle:
println!("u8 wheel: 250 + 10 = {}", 250u8.wrapping_add(10));
}
The edge cases, in one screen: None vs Some(42), the wrap to
-2147483648, the pin at 2147483647, and None for unsigned
3 - 5 (there is no -2 in u32 — going below zero is overflow in
the other direction). The last line is wraparound as a feature:
a 256-position wheel steps from 250 by 10 and lands on 4.
Check the concept
One question at a time. Unsure? Revisit the lecture, then answer.
The challenge
Pass the quiz to unlock the challenge — your code will still be waiting here.