Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Functional Patterns

Functional programming utilities for composition and lazy evaluation.

pipe

Thread a value through a sequence of functions:

#![allow(unused)]
fn main() {
use rok_utils::fp::pipe;

let result = pipe(5, vec![
    |x| x + 1,
    |x| x * 2,
    |x| x - 3,
]);

// (5 + 1) * 2 - 3 = 9
assert_eq!(result, 9);
}

compose

Create new functions by composing two functions:

#![allow(unused)]
fn main() {
use rok_utils::fp::compose;

let add_then_double = compose(
    |x: i32| x * 2,
    |x: i32| x + 1,
);

assert_eq!(add_then_double(5), 12); // (5 + 1) * 2
}

tap

Execute side effects without changing the value:

#![allow(unused)]
fn main() {
use rok_utils::fp::tap;

let mut log = Vec::new();
let result = tap(42, |v| log.push(*v));

assert_eq!(result, 42);
assert_eq!(log, vec![42]);
}

Lazy

Lazily initialized value:

#![allow(unused)]
fn main() {
use rok_utils::fp::Lazy;

let config = Lazy::new(|| {
    println!("Initializing...");
    "config_value".to_string()
});

println!("Before access");
let value = config.get();
println!("After access: {}", value);
}

memoize

Cache function results:

#![allow(unused)]
fn main() {
use rok_utils::fp::memoize;

let expensive = memoize(|x: i32| {
    println!("Computing...");
    x * x
});

expensive(5); // Computes
expensive(5); // Uses cached result
expensive(3); // Computes new value
}

retry

Retry failed operations:

#![allow(unused)]
fn main() {
use rok_utils::fp::retry;

let mut attempts = 0;
let result = retry(3, || {
    attempts += 1;
    if attempts < 2 {
        Err("failed")
    } else {
        Ok("success")
    }
});

assert_eq!(result.unwrap(), "success");
assert_eq!(attempts, 2);
}

or_default

Get value from Option or default:

#![allow(unused)]
fn main() {
use rok_utils::fp::or_default;

assert_eq!(or_default(Some(42)), 42);
assert_eq!(or_default(None::<i32>), 0);
}

See Also