# Combinators

## What is a combinator?

• One meaning of “combinator” is a more informal sense referring to the combinator pattern, a style of organizing libraries centered around the idea of combining things. Usually there is some type T, some functions for constructing “primitive” values of type T, and some “combinators” which can combine values of type T in various ways to build up more complex values of type T. The other definition is “function with no free variables”.

• A combinator is a function which builds program fragments from program fragments; in a sense the programmer using combinators constructs much of the desired program automatically, rather that writing every detail by hand.
__ John Hughes—Generalizing Monads to Arrows via Functional Programming Concepts

The exact definition of “combinators” in Rust ecosystem is bit unclear.

• `or()`, `and()`, `or_else()`, `and_then()`
Combine two values of type T and return same type T.

• `filter()` for `Option` types
Filter type T by using a closure as a conditional function
Return same type T

• `map()`, `map_err()`
Convert type T by applying a closure.
▸ The data type of the value inside T can be changed.
ex. `Some<&str>` can be converted to `Some<usize>` or `Err<&str>` to `Err<isize>` and etc.

• `map_or()`, `map_or_else()`
Transform type T by applying a closure & return the value inside type T.
▸ For `None` and `Err`, a default value or another closure is applied.

• `ok_or()`, `ok_or_else()` for `Option` types
Transform `Option` type into a `Result` type.

• `as_ref()`, `as_mut()`
Transform type T into a reference or a mutable reference.

## or() and and()

While combining two expressions, which return either `Option`/ `Result`

• `or()`: If either one got `Some` or `Ok`, that value returns immediately.
• `and()`: If both got `Some` or `Ok`, the value in the second expression returns. If either one got `None` or `Err` that value returns immediately.

``````fn main() {
let s1 = Some("some1");
let s2 = Some("some2");
let n: Option<&str> = None;

let o1: Result<&str, &str> = Ok("ok1");
let o2: Result<&str, &str> = Ok("ok2");
let e1: Result<&str, &str> = Err("error1");
let e2: Result<&str, &str> = Err("error2");

assert_eq!(s1.or(s2), s1); // Some1 or Some2 = Some1
assert_eq!(s1.or(n), s1);  // Some or None = Some
assert_eq!(n.or(s1), s1);  // None or Some = Some
assert_eq!(n.or(n), n);    // None1 or None2 = None2

assert_eq!(o1.or(o2), o1); // Ok1 or Ok2 = Ok1
assert_eq!(o1.or(e1), o1); // Ok or Err = Ok
assert_eq!(e1.or(o1), o1); // Err or Ok = Ok
assert_eq!(e1.or(e2), e2); // Err1 or Err2 = Err2

assert_eq!(s1.and(s2), s2); // Some1 and Some2 = Some2
assert_eq!(s1.and(n), n);   // Some and None = None
assert_eq!(n.and(s1), n);   // None and Some = None
assert_eq!(n.and(n), n);    // None1 and None2 = None1

assert_eq!(o1.and(o2), o2); // Ok1 and Ok2 = Ok2
assert_eq!(o1.and(e1), e1); // Ok and Err = Err
assert_eq!(e1.and(o1), e1); // Err and Ok = Err
assert_eq!(e1.and(e2), e1); // Err1 and Err2 = Err1
}
``````

🔎 Rust nightly support `xor()` for `Option` types, which returns `Some` only if one expression got `Some`, but not both.

## or_else()

Similar to `or()`. The only difference is, the second expression should be a closure which returns same type T.

``````fn main() {
// or_else with Option
let s1 = Some("some1");
let s2 = Some("some2");
let fn_some = || Some("some2"); // similar to: let fn_some = || -> Option<&str> { Some("some2") };

let n: Option<&str> = None;
let fn_none = || None;

assert_eq!(s1.or_else(fn_some), s1);  // Some1 or_else Some2 = Some1
assert_eq!(s1.or_else(fn_none), s1);  // Some or_else None = Some
assert_eq!(n.or_else(fn_some), s2);   // None or_else Some = Some
assert_eq!(n.or_else(fn_none), None); // None1 or_else None2 = None2

// or_else with Result
let o1: Result<&str, &str> = Ok("ok1");
let o2: Result<&str, &str> = Ok("ok2");
let fn_ok = |_| Ok("ok2"); // similar to: let fn_ok = |_| -> Result<&str, &str> { Ok("ok2") };

let e1: Result<&str, &str> = Err("error1");
let e2: Result<&str, &str> = Err("error2");
let fn_err = |_| Err("error2");

assert_eq!(o1.or_else(fn_ok), o1);  // Ok1 or_else Ok2 = Ok1
assert_eq!(o1.or_else(fn_err), o1); // Ok or_else Err = Ok
assert_eq!(e1.or_else(fn_ok), o2);  // Err or_else Ok = Ok
assert_eq!(e1.or_else(fn_err), e2); // Err1 or_else Err2 = Err2
}
``````

## and_then()

Similar to `and()`. The only difference is, the second expression should be a closure which returns same type T.

``````fn main() {
// and_then with Option
let s1 = Some("some1");
let s2 = Some("some2");
let fn_some = |_| Some("some2"); // similar to: let fn_some = |_| -> Option<&str> { Some("some2") };

let n: Option<&str> = None;
let fn_none = |_| None;

assert_eq!(s1.and_then(fn_some), s2); // Some1 and_then Some2 = Some2
assert_eq!(s1.and_then(fn_none), n);  // Some and_then None = None
assert_eq!(n.and_then(fn_some), n);   // None and_then Some = None
assert_eq!(n.and_then(fn_none), n);   // None1 and_then None2 = None1

// and_then with Result
let o1: Result<&str, &str> = Ok("ok1");
let o2: Result<&str, &str> = Ok("ok2");
let fn_ok = |_| Ok("ok2"); // similar to: let fn_ok = |_| -> Result<&str, &str> { Ok("ok2") };

let e1: Result<&str, &str> = Err("error1");
let e2: Result<&str, &str> = Err("error2");
let fn_err = |_| Err("error2");

assert_eq!(o1.and_then(fn_ok), o2);  // Ok1 and_then Ok2 = Ok2
assert_eq!(o1.and_then(fn_err), e2); // Ok and_then Err = Err
assert_eq!(e1.and_then(fn_ok), e1);  // Err and_then Ok = Err
assert_eq!(e1.and_then(fn_err), e1); // Err1 and_then Err2 = Err1
}
``````

## filter()

💡 Usually in programming languages `filter` functions are used with arrays or iterators to create a new array/ iterator by filtering own elements via a function/ closure. Rust also provides `filter()` as an iterator adaptor to apply a closure on each element of an iterator to transform it into another iterator. However in here we are talking about the functionality of `filter()` with `Option` types.

The same `Some` type is returned, only if we pass a `Some` value and the given closure returned true for it. `None` is returned, if `None` type passed or the closure returned false. The closure uses the value inside `Some` as an argument. Still Rust support `filter()` only for `Option` types.

``````fn main() {
let s1 = Some(3);
let s2 = Some(6);
let n = None;

let fn_is_even = |x: &i8| x % 2 == 0;

assert_eq!(s1.filter(fn_is_even), n);  // Some(3) -> 3 is not even -> None
assert_eq!(s2.filter(fn_is_even), s2); // Some(6) -> 6 is even -> Some(6)
assert_eq!(n.filter(fn_is_even), n);   // None -> no value -> None
}
``````

## map() and map_err()

💡 Usually in programming languages `map()` functions are used with arrays or iterators, to apply a closure on each element of the array or iterator. Rust also provides `map()` as an iterator adaptor to apply a closure on each element of an iterator to transform it into another iterator. However in here we are talking about the functionality of `map()` with `Option` and `Result` types.

• `map()` : Convert type T by applying a closure. The data type of `Some` or `Ok` blocks can be changed according to the return type of the closure. Convert `Option<T>` to `Option<U>`, `Result<T, E>` to `Result<U, E>`

⭐ Via `map()`, only `Some` and `Ok` values are getting changed. No affect to the values inside `Err` (`None` doesn’t contain any value at all).

``````fn main() {
let s1 = Some("abcde");
let s2 = Some(5);

let n1: Option<&str> = None;
let n2: Option<usize> = None;

let o1: Result<&str, &str> = Ok("abcde");
let o2: Result<usize, &str> = Ok(5);

let e1: Result<&str, &str> = Err("abcde");
let e2: Result<usize, &str> = Err("abcde");

let fn_character_count = |s: &str| s.chars().count();

assert_eq!(s1.map(fn_character_count), s2); // Some1 map = Some2
assert_eq!(n1.map(fn_character_count), n2); // None1 map = None2

assert_eq!(o1.map(fn_character_count), o2); // Ok1 map = Ok2
assert_eq!(e1.map(fn_character_count), e2); // Err1 map = Err2
}
``````
• `map_err()` for `Result` types : The data type of `Err` blocks can be changed according to the return type of the closure. Convert `Result<T, E>` to `Result<T, F>`.

⭐ Via `map_err()`, only `Err` values are getting changed. No affect to the values inside `Ok`.

``````fn main() {
let o1: Result<&str, &str> = Ok("abcde");
let o2: Result<&str, isize> = Ok("abcde");

let e1: Result<&str, &str> = Err("404");
let e2: Result<&str, isize> = Err(404);

let fn_character_count = |s: &str| -> isize { s.parse().unwrap() }; // convert str to isize

assert_eq!(o1.map_err(fn_character_count), o2); // Ok1 map = Ok2
assert_eq!(e1.map_err(fn_character_count), e2); // Err1 map = Err2
}
``````

## map_or() and map_or_else()

Hope you remember the functionality of `unwrap_or()` and `unwrap_or_else()` functions. These functions also bit similar to them. But `map_or()` and `map_or_else()` apply a closure on `Some` and `Ok` values and return the value inside type T.

• `map_or()` : Support only for `Option` types (not supporting `Result`). Apply the closure to the value inside `Some` and return the output according to the closure. The given default value is returned for `None` types.

``````fn main() {
const V_DEFAULT: i8 = 1;

let s = Some(10);
let n: Option<i8> = None;
let fn_closure = |v: i8| v + 2;

assert_eq!(s.map_or(V_DEFAULT, fn_closure), 12);
assert_eq!(n.map_or(V_DEFAULT, fn_closure), V_DEFAULT);
}
``````
• `map_or_else()` : Support for both `Option` and `Result` types (`Result` still nightly only). Similar to `map_or()` but should provide another closure instead a default value for the first parameter.

`None` types doesn’t contain any value. So no need to pass anything to the closure as input with `Option` types. But `Err` types contain some value inside it. So default closure should able to read it as an input, while using this with `Result` types.

``````#![feature(result_map_or_else)] // enable unstable library feature 'result_map_or_else' on nightly
fn main() {
let s = Some(10);
let n: Option<i8> = None;

let fn_closure = |v: i8| v + 2;
let fn_default = || 1; // None doesn't contain any value. So no need to pass anything to closure as input.

assert_eq!(s.map_or_else(fn_default, fn_closure), 12);
assert_eq!(n.map_or_else(fn_default, fn_closure), 1);

let o = Ok(10);
let e = Err(5);
let fn_default_for_result = |v: i8| v + 1; // Err contain some value inside it. So default closure should able to read it as input

assert_eq!(o.map_or_else(fn_default_for_result, fn_closure), 12);
assert_eq!(e.map_or_else(fn_default_for_result, fn_closure), 6);
}
``````

## ok_or() and ok_or_else()

As mentioned earlier, `ok_or()`, `ok_or_else()` transform `Option` type into `Result` type. `Some` to `Ok` and `None` to `Err`.

• `ok_or()` : A default `Err` message should pass as argument.

``````fn main() {
const ERR_DEFAULT: &str = "error message";

let s = Some("abcde");
let n: Option<&str> = None;

let o: Result<&str, &str> = Ok("abcde");
let e: Result<&str, &str> = Err(ERR_DEFAULT);

assert_eq!(s.ok_or(ERR_DEFAULT), o); // Some(T) -> Ok(T)
assert_eq!(n.ok_or(ERR_DEFAULT), e); // None -> Err(default)
}
``````
• `ok_or_else()` : Similar to `ok_or()`. A closure should be passed as the argument.

``````fn main() {
let s = Some("abcde");
let n: Option<&str> = None;
let fn_err_message = || "error message";

let o: Result<&str, &str> = Ok("abcde");
let e: Result<&str, &str> = Err("error message");

assert_eq!(s.ok_or_else(fn_err_message), o); // Some(T) -> Ok(T)
assert_eq!(n.ok_or_else(fn_err_message), e); // None -> Err(default)
}
``````

## as_ref() and as_mut()

🔎 As mentioned earlier, these functions are used to borrow type T as a reference or as a mutable reference.

• `as_ref()` : Convert `Option<T>` to `Option<&T>` and `Result<T, E>` to `Result<&T, &E>`
• `as_mut()` : Converts `Option<T>` to `Option<&mut T>` and `Result<T, E>` to `Result<&mut T, &mut E>`