Basic Operations
introduction
difference between macros and functions: macros have the
!
symbolthey behave similarly
a macro can take an arbitrary number of arguments, cant do that if it were a regular function
fn main() {
println!("Hello, world!");
}
if statements dont need to have parentheses
fn main() {
let x = 42;
if x == 42 {
println!("x is 42");
} else if x % 2 == 0 {
println!("x is even");
} else {
println!("x is odd");
}
}
if statements can have return values
fn main() {
let x = 42;
let msg = if x == 42 {
"x is 42"
} else if x % 2 == 0 {
"even"
} else {
"odd"
};
println!("{}", msg);
}
rust makes a distinction between string literals and string types
println
statement only accepts string literalsfor loops:
fn main() {
for i in 0..10 {
println!("{}", i);
}
}
fizzbuzz
fn main() {
for i in 0..20 {
if i % 3 == 0 && i % 5 == 0 {
println!("Fizzbuzz");
} else if i % 3 == 0 {
println!("Fizz");
} else if i % 5 == 0 {
println!("buzz");
} else {
println!("{}", i);
}
}
}
integers and floats
default integer type is the signed
i32
, can use bigger types likei64
ori128
, or unsignedu128
if we dont need negative valuestwo types of floats,
f32
andf64
all integer sizes supported by rust: 8 16 32 64 128
fn integer() -> i32 {
return 42;
}
fn float() -> f64 {
return 3.142;
}
fn main() {
let int = integer();
let flt = float();
println!("{}", int);
println!("{}", flt);
}
overflows and underflows
// panic, due to underflow, returns 10 if i8 is used
fn main() {
let mut x: u8 = 10;
x = x - 20;
println!("{}", x);
}
we can return values without using the return keyword, if the last value in the function does not end with a semicolon
// idiomatic rust
fn mul(x: i32, y:i32) -> i32 {
x * y
}
// "traditional" representation
fn mul(x: i32, y:i32) -> i32 {
return x * y;
}
if we want to do an early return, we would have to use the return statement
fn factorial(n: u128) -> u128 {
if n == 0 || n == 1 {
return 1;
}
n * factorial(n-1)
}
this still compiles because the final return value originates from the if statement
will not work if we add semicolons to after the x and y values
fn min(x: i32, y: i32) -> i32 {
if x < y { x } else { y }
}
vectors are like lists/arrays in other languages
have to use a different format string if we want to print a vector
fn main() {
let mut x: Vec<i32> = Vec::new();
x.push(5);
x.push(10);
println!("{:?}", x);
}
loop through vector length and print elements
fn main() {
let mut x: Vec<i32> = Vec::new();
x.push(5);
x.push(10);
for i in 0..x.len() {
println!("{}", x[i]);
}
}
popping value from Vector may return
Option<i32>
options are an important part of why is rust is safer than other languages, because when you pop an item out of an array, there is no guarantee what type it is
generally rust returns options when there’s a possibility that an operation might fail
forces user to deal with an invalid value at compile time
fn main() {
let mut v: Vec<i32> = [1, 2, 3].to_vec();
let last = v.pop();
println!("{:?}", last); // prints Some(3)
}
an option can be one of two types: some and none
none - returns when we would usually expect null pointers or exceptions
some - returns when succeeds
cannot treat options like the value they contain, e.g. cannot add an integer to an option
// will return Option as someone might try to convert a value that is invalid
fn main() {
let my_char = '3'.to_digit(10);
println!("{:?}", my_char); // returns Some(3)
}
rust does not always produce an option, will panic in some other situations, for example when accessing an array out of bounds
// this code panics
fn main() {
let my_vec = Vec::from([1, 2, 4]);
println!("{:?}", my_vec[10]);
}
can convert to another form to return an option instead
fn main() {
let my_vec = Vec::from([1, 2, 4]);
println!("{:?}", my_vec.get(10)); // returns None
let x: i32 = 1;
println!("{:?}", x.checked_div(10)); // returns Some(0)
}
convert
Some(3)
into a regular 3
Last updated