118 lines
3.0 KiB
Rust
118 lines
3.0 KiB
Rust
fn fizzbuzz(n: i32) {
|
|
for i in 1..=n {
|
|
if i % 15 == 0 {
|
|
println!("FizzBuzz");
|
|
} else if i % 5 == 0 {
|
|
println!("Buzz");
|
|
} else if i % 3 == 0 {
|
|
println!("Fizz");
|
|
} else {
|
|
println!("{i}");
|
|
}
|
|
}
|
|
}
|
|
|
|
// Associated functions (without self) and Methods (with self)
|
|
// are the ways of connecting a function to a type.
|
|
struct Point {
|
|
x: i8,
|
|
y: i8,
|
|
}
|
|
|
|
impl Point {
|
|
// Associated functions
|
|
fn origin() -> Point {
|
|
Point { x: 0, y: 0 }
|
|
}
|
|
|
|
fn new(x: i8, y: i8) -> Point {
|
|
Point { x, y }
|
|
}
|
|
|
|
// Methods
|
|
fn run(&mut self, x: i8, y: i8) {
|
|
self.x += x;
|
|
self.y += y;
|
|
}
|
|
|
|
// bad practice, just for practice
|
|
fn to_string(&self) -> String {
|
|
format!("{} {}", self.x, self.y)
|
|
}
|
|
}
|
|
|
|
// when used as a parameter in a function
|
|
// the closures complete type must be annotated using one of a few traits.
|
|
// In order to decrease restriction, they are:
|
|
// Fn: the closure uses the captured value by reference (&T)
|
|
// FnMut: the closure uses the captured value by mutable reference (&mut T)
|
|
// FnOnce: the closure uses the captured value by value (T)
|
|
//
|
|
// NOTE: this function could also take a normal function as a parameter, not only a closure
|
|
fn apply<F>(f: F)
|
|
where
|
|
F: FnOnce(),
|
|
{
|
|
println!("About to run a closure...");
|
|
f();
|
|
}
|
|
|
|
fn create_fn() -> impl Fn() {
|
|
let text = "Fn".to_owned();
|
|
move || println!("Info: {}", text) // move converts the used variables to variables captured by
|
|
// value;
|
|
}
|
|
|
|
fn divergin_one() -> ! {
|
|
panic!("This will never return! PANIC");
|
|
}
|
|
|
|
pub fn functions_module() {
|
|
fizzbuzz(10);
|
|
|
|
println!("-- Associated functions and Methods --");
|
|
|
|
let mut my_point = Point::new(4, 5);
|
|
println!("My point: {}", my_point.to_string());
|
|
|
|
my_point.run(20, 1);
|
|
println!("My point: {}", my_point.to_string());
|
|
|
|
// Closures are made to allow access to the enclosing environment,
|
|
// similar to JS functions inside functions
|
|
let mut closure_run = |x: i8, y: i8| {
|
|
my_point.x += x;
|
|
my_point.y += y;
|
|
};
|
|
|
|
closure_run(10, 15);
|
|
println!("My point: {}", my_point.to_string());
|
|
// closure_run(10, 15);
|
|
// println!("My point: {}", my_point.to_string());
|
|
|
|
// move keyword forces the closure to take ownership of captured variables
|
|
let mut closure_run = move |x: i8, y: i8| {
|
|
my_point.x += x;
|
|
my_point.y += y;
|
|
};
|
|
|
|
// Rust provides higher order functions, such as
|
|
// - map : .map(|n| n * n)
|
|
// - filter : .filter(|&n| is_add(n))
|
|
// - take_while : .take_while(|&n| n < upper)
|
|
|
|
// Diverging functions
|
|
// Never return, marked with: !
|
|
// Useful on divergin situations where an exact type is required
|
|
for i in 0..5 {
|
|
let value: u32 = match i % 2 == 0 {
|
|
true => 5,
|
|
false => continue,
|
|
};
|
|
println!("The value is pair and {value}");
|
|
}
|
|
|
|
// NOTE: Bad example since it's not really useful
|
|
divergin_one();
|
|
}
|