#![allow(unused)]
fn main() {
//! This crate shows us different ways of dealing with errors in a Rust program.
//! You will find examples of [Option], [Result] and [panic!].
pub mod binary_operator;
pub mod find;
pub mod io;
#[cfg(test)]
mod tests {
use crate::binary_operator::*;
use crate::find::find_with_hof;
const TAB: [i32; 9] = [10, 32, 12, 43, 52, 53, 83, 2, 9];
const TAB_EMPTY: [i32; 0] = [];
const MIN_TAB: i32 = 2;
const MAX_TAB: i32 = 83;
#[test]
fn test_find_with_option_min() {
let min: Option<i32> = find_with_hof(&TAB, |x: i32, y: i32| if x <= y { x } else { y });
assert!(min == Some(MIN_TAB));
}
#[test]
fn test_find_with_option_max() {
let max: Option<i32> = find_with_hof(&TAB, |x: i32, y: i32| if x >= y { x } else { y });
assert!(max == Some(MAX_TAB));
}
#[test]
fn test_find_with_option_empty() {
let min: Option<i32> =
find_with_hof(&TAB_EMPTY, |x: i32, y: i32| if x <= y { x } else { y });
assert!(min.is_none());
}
#[test]
fn test_minimum_operator() {
let f = minimum_operator::<i32>();
assert!(f(5, 10) == 5);
}
#[test]
fn test_maximum_operator() {
let f = maximum_operator::<i32>();
assert!(f(5, 10) == 10);
}
#[test]
fn test_sum_operator() {
let f = sum_operator::<i32>();
assert!(f(5, 10) == 15);
}
#[test]
fn test_mul_operator() {
let f = mul_operator::<i32>();
assert!(f(5, 10) == 50);
}
}
}
use closures::binary_operator::{minimum_operator, sum_operator};
use closures::find::find_with_hof;
use closures::io;
fn main() {
let tab = io::read_command_line_correct();
println!("Among the elements in the list:");
io::print_tab(&tab);
//ANCHOR: min_usage
let min = find_with_hof(&tab, minimum_operator());
match min {
Some(val) => println!("The minimum value is {}", val),
None => eprintln!("There is no minimum"),
}
//ANCHOR_END: min_usage
//ANCHOR: max_variable
let max_op: fn(i32, i32) -> i32 = |x, y| if x >= y { x } else { y };
//ANCHOR_END: max_variable
//ANCHOR: option_filter
let max_val: Option<i32> = find_with_hof(&tab, max_op);
let odd_max: Option<i32> = max_val.filter(|x| x % 2 == 1);
match odd_max {
Some(_) => println!("The maximum value is an odd number"),
None => {
if max_val.is_some() {
println!("The maximum value is an even number")
} else {
eprintln!("There is no maximum")
}
}
}
//ANCHOR_END: option_filter
//ANCHOR: option_map
let two: f32 = 2.0f32;
let sum: Option<i32> = find_with_hof(&tab, sum_operator());
let half: Option<f32> = sum.map(|x: i32| (x as f32) / two);
match half {
Some(val) => println!("The sum of the elements divided by two is {}", val),
None => eprintln!("There is no sum"),
}
//ANCHOR_END: option_map
}
// ANCHOR: binary_operator
pub type BinaryOperator<T> = fn(T, T) -> T;
// ANCHOR_END: binary_operator
/// Returns a closure that computes the minimum
/// between two elements of type T.
/// # Example
///
/// ```
/// # use closures::binary_operator::{minimum_operator};
/// # fn main() {
/// let f = minimum_operator();
/// assert!(f(1,2) == 1);
/// # }
/// ```
// ANCHOR: minimum_operator
pub fn minimum_operator<T: PartialOrd>() -> BinaryOperator<T> {
|x: T, y: T| if x <= y { x } else { y }
}
// ANCHOR_END: minimum_operator
/// Returns a closure that computes the maximum
/// between two elements of type T.
/// # Example
///
/// ```
/// # use closures::binary_operator::{maximum_operator};
/// # fn main() {
/// let f = maximum_operator();
/// assert!(f(1,2) == 2);
/// # }
/// ```
// ANCHOR: maximum_operator
pub fn maximum_operator<T: PartialOrd>() -> BinaryOperator<T> {
|x: T, y: T| if x >= y { x } else { y }
}
// ANCHOR_END: maximum_operator
/// Returns a closure that computes the sum
/// of two elements of type T.
/// # Example
///
/// ```
/// # use closures::binary_operator::{sum_operator};
/// # fn main() {
/// let f = sum_operator();
/// assert!(f(1,2) == 3);
/// # }
/// ```
// ANCHOR: sum_operator
pub fn sum_operator<T: std::ops::Add<Output = T>>() -> BinaryOperator<T> {
|x: T, y: T| x + y
}
// ANCHOR_END: sum_operator
/// Returns a closure that computes the product
/// of two elements of type T.
/// # Example
///
/// ```
/// # use closures::binary_operator::{mul_operator};
/// # fn main() {
/// let f = mul_operator();
/// assert!(f(1,2) == 2);
/// # }
/// ```
// ANCHOR: mul_operator
pub fn mul_operator<T: std::ops::Mul<Output = T>>() -> BinaryOperator<T> {
|x: T, y: T| x * y
}
// ANCHOR_END: mul_operator
//! Contains the core logic of the library, allowing to store generic values
//! (or their absence) and manipulate them.
//! We demonstrates three kind of way to deal with errors
use crate::binary_operator::BinaryOperator;
/// Computes the result of a binary reduction of an Array of a type T.
/// Take the binary operation as a function.
/// Returns a [Option::Some] containing the result value
/// or [Option::None] if the array was empty.
///
/// # Example
///
/// ```
/// # use closures::find::{find_with_hof};
/// # fn main() {
/// let tab = [10, 32, 12, 43, 52, 53, 83, 2, 9];
/// let min = find_with_hof(&tab,|x, y| if x <= y { x } else { y });
/// assert!(min == Some(2));
/// # }
/// ```
// ANCHOR: find_with_hof
pub fn find_with_hof<T: Copy>(tab: &[T], op: BinaryOperator<T>) -> Option<T> {
let mut res = None;
// Here, if T is Copyable, t is not moved in the loop
for t in tab {
if let Some(val) = res {
res = Some(op(val, *t))
} else {
res = Some(*t)
}
}
res
}
// ANCHOR_END: find_with_hof
#![allow(unused)]
fn main() {
//! Contains functions to interact with the user, either
//! by reading inputs from the terminal, either by writing values
//! in it.
/// Poorly emulates the parsing of a command line.
pub fn read_command_line_correct() -> [i32; 9] {
[10, 32, 12, 43, 52, 53, 83, 2, 9]
}
/// Poorly emulates the parsing of a command line.
pub fn read_empty_command_line() -> [i32; 0] {
[]
}
/// Prints all the elements of the `tab`.
/// Tab is borrowed here
pub fn print_tab(tab: &[i32]) {
print!("[ ");
for t in tab {
print!("{} ", t);
}
println!("]");
}
}