FnSupplierOps

Trait FnSupplierOps 

Source
pub trait FnSupplierOps<T>:
    FnMut() -> T
    + Sized
    + 'static {
    // Provided methods
    fn map<U, M>(self, mapper: M) -> BoxSupplier<U>
       where M: Mapper<T, U> + 'static,
             U: 'static,
             T: 'static { ... }
    fn filter<P>(self, predicate: P) -> BoxSupplier<Option<T>>
       where P: FnMut(&T) -> bool + 'static,
             T: 'static { ... }
    fn zip<U>(self, other: BoxSupplier<U>) -> BoxSupplier<(T, U)>
       where U: 'static,
             T: 'static { ... }
    fn memoize(self) -> BoxSupplier<T>
       where T: Clone + 'static { ... }
}
Expand description

Extension trait providing supplier operations for closures

Provides composition methods (map, filter, zip, memoize) for closures implementing FnMut() -> T without requiring explicit wrapping in BoxSupplier.

This trait is automatically implemented for all closures and function pointers that implement FnMut() -> T.

§Design Rationale

While closures automatically implement Supplier<T> through blanket implementation, they don’t have access to instance methods like map, filter, and zip. This extension trait provides those methods, returning BoxSupplier for maximum flexibility.

§Examples

§Map transformation

use prism3_function::{Supplier, FnSupplierOps};

let mut counter = 0;
let mut mapped = (move || {
    counter += 1;
    counter
}).map(|x| x * 2);

assert_eq!(mapped.get(), 2);
assert_eq!(mapped.get(), 4);

§Filter values

use prism3_function::{Supplier, FnSupplierOps};

let mut counter = 0;
let mut filtered = (move || {
    counter += 1;
    counter
}).filter(|x| x % 2 == 0);

assert_eq!(filtered.get(), None);     // 1 is odd
assert_eq!(filtered.get(), Some(2));  // 2 is even

§Combine with zip

use prism3_function::{Supplier, FnSupplierOps, BoxSupplier};

let first = || 42;
let second = BoxSupplier::new(|| "hello");
let mut zipped = first.zip(second);

assert_eq!(zipped.get(), (42, "hello"));

§Author

Haixing Hu

Provided Methods§

Source

fn map<U, M>(self, mapper: M) -> BoxSupplier<U>
where M: Mapper<T, U> + 'static, U: 'static, T: 'static,

Maps the output using a transformation function.

Consumes the closure and returns a new supplier that applies the mapper to each output.

§Parameters
  • mapper - The mapper to apply to the output
§Returns

A new mapped BoxSupplier<U>

§Examples
use prism3_function::{Supplier, FnSupplierOps};

let mut mapped = (|| 10)
    .map(|x| x * 2)
    .map(|x| x + 5);
assert_eq!(mapped.get(), 25);
Examples found in repository?
examples/closure_supplier_ops_demo.rs (line 28)
18fn main() {
19    println!("=== Closure Supplier Operations Demo ===\n");
20
21    // 1. FnMut closure using map
22    println!("1. FnMut closure using map:");
23    let mut counter = 0;
24    let mut mapped = (move || {
25        counter += 1;
26        counter
27    })
28    .map(|x| x * 2);
29
30    println!("   First call: {}", mapped.get());
31    println!("   Second call: {}\n", mapped.get());
32
33    // 2. FnMut closure using filter
34    println!("2. FnMut closure using filter:");
35    let mut counter2 = 0;
36    let mut filtered = (move || {
37        counter2 += 1;
38        counter2
39    })
40    .filter(|x| x % 2 == 0);
41
42    println!("   First call (odd number): {:?}", filtered.get());
43    println!("   Second call (even number): {:?}\n", filtered.get());
44
45    // 3. FnMut closure using memoize
46    println!("3. FnMut closure using memoize:");
47    let mut call_count = 0;
48    let mut memoized = (move || {
49        call_count += 1;
50        println!("   Underlying function called {} times", call_count);
51        42
52    })
53    .memoize();
54
55    println!("   First call: {}", memoized.get());
56    println!("   Second call: {}", memoized.get());
57    println!("   Third call: {}\n", memoized.get());
58
59    // 4. Fn closure using map (Fn also implements FnMut, so can use FnSupplierOps)
60    println!("4. Fn closure using map:");
61    let mut mapped_readonly = (|| 10).map(|x| x * 3).map(|x| x + 5);
62    println!("   Result: {}\n", mapped_readonly.get());
63
64    // 5. Fn closure using filter (Fn also implements FnMut, so can use FnSupplierOps)
65    println!("5. Fn closure using filter:");
66    let mut filtered_readonly = (|| 42).filter(|x| x % 2 == 0);
67    println!("   Filtered even number: {:?}\n", filtered_readonly.get());
68
69    // 6. Chained operations
70    println!("6. Chained operations:");
71    let mut counter3 = 0;
72    let mut chained = (move || {
73        counter3 += 1;
74        counter3
75    })
76    .map(|x| x * 2)
77    .filter(|x| *x > 5)
78    .map(|opt: Option<i32>| opt.unwrap_or(0));
79
80    println!("   First call: {}", chained.get()); // 2, filtered out
81    println!("   Second call: {}", chained.get()); // 4, filtered out
82    println!("   Third call: {}", chained.get()); // 6, passed
83    println!("   Fourth call: {}\n", chained.get()); // 8, passed
84
85    println!("=== Demo completed ===");
86}
Source

fn filter<P>(self, predicate: P) -> BoxSupplier<Option<T>>
where P: FnMut(&T) -> bool + 'static, T: 'static,

Filters output based on a predicate.

Returns a new supplier that returns Some(value) if the predicate is satisfied, None otherwise.

§Parameters
  • predicate - The predicate to test the supplied value
§Returns

A new filtered BoxSupplier<Option<T>>

§Examples
use prism3_function::{Supplier, FnSupplierOps};

let mut counter = 0;
let mut filtered = (move || {
    counter += 1;
    counter
}).filter(|x| x % 2 == 0);

assert_eq!(filtered.get(), None);     // 1 is odd
assert_eq!(filtered.get(), Some(2));  // 2 is even
Examples found in repository?
examples/closure_supplier_ops_demo.rs (line 40)
18fn main() {
19    println!("=== Closure Supplier Operations Demo ===\n");
20
21    // 1. FnMut closure using map
22    println!("1. FnMut closure using map:");
23    let mut counter = 0;
24    let mut mapped = (move || {
25        counter += 1;
26        counter
27    })
28    .map(|x| x * 2);
29
30    println!("   First call: {}", mapped.get());
31    println!("   Second call: {}\n", mapped.get());
32
33    // 2. FnMut closure using filter
34    println!("2. FnMut closure using filter:");
35    let mut counter2 = 0;
36    let mut filtered = (move || {
37        counter2 += 1;
38        counter2
39    })
40    .filter(|x| x % 2 == 0);
41
42    println!("   First call (odd number): {:?}", filtered.get());
43    println!("   Second call (even number): {:?}\n", filtered.get());
44
45    // 3. FnMut closure using memoize
46    println!("3. FnMut closure using memoize:");
47    let mut call_count = 0;
48    let mut memoized = (move || {
49        call_count += 1;
50        println!("   Underlying function called {} times", call_count);
51        42
52    })
53    .memoize();
54
55    println!("   First call: {}", memoized.get());
56    println!("   Second call: {}", memoized.get());
57    println!("   Third call: {}\n", memoized.get());
58
59    // 4. Fn closure using map (Fn also implements FnMut, so can use FnSupplierOps)
60    println!("4. Fn closure using map:");
61    let mut mapped_readonly = (|| 10).map(|x| x * 3).map(|x| x + 5);
62    println!("   Result: {}\n", mapped_readonly.get());
63
64    // 5. Fn closure using filter (Fn also implements FnMut, so can use FnSupplierOps)
65    println!("5. Fn closure using filter:");
66    let mut filtered_readonly = (|| 42).filter(|x| x % 2 == 0);
67    println!("   Filtered even number: {:?}\n", filtered_readonly.get());
68
69    // 6. Chained operations
70    println!("6. Chained operations:");
71    let mut counter3 = 0;
72    let mut chained = (move || {
73        counter3 += 1;
74        counter3
75    })
76    .map(|x| x * 2)
77    .filter(|x| *x > 5)
78    .map(|opt: Option<i32>| opt.unwrap_or(0));
79
80    println!("   First call: {}", chained.get()); // 2, filtered out
81    println!("   Second call: {}", chained.get()); // 4, filtered out
82    println!("   Third call: {}", chained.get()); // 6, passed
83    println!("   Fourth call: {}\n", chained.get()); // 8, passed
84
85    println!("=== Demo completed ===");
86}
Source

fn zip<U>(self, other: BoxSupplier<U>) -> BoxSupplier<(T, U)>
where U: 'static, T: 'static,

Combines this supplier with another, producing a tuple.

Consumes both suppliers and returns a new supplier that produces (T, U) tuples.

§Parameters
  • other - The other supplier to combine with
§Returns

A new BoxSupplier<(T, U)>

§Examples
use prism3_function::{Supplier, FnSupplierOps, BoxSupplier};

let first = || 42;
let second = BoxSupplier::new(|| "hello");
let mut zipped = first.zip(second);

assert_eq!(zipped.get(), (42, "hello"));
Source

fn memoize(self) -> BoxSupplier<T>
where T: Clone + 'static,

Creates a memoizing supplier.

Returns a new supplier that caches the first value it produces. All subsequent calls return the cached value.

§Returns

A new memoized BoxSupplier<T>

§Examples
use prism3_function::{Supplier, FnSupplierOps};

let mut call_count = 0;
let mut memoized = (move || {
    call_count += 1;
    42
}).memoize();

assert_eq!(memoized.get(), 42); // Calls underlying function
assert_eq!(memoized.get(), 42); // Returns cached value
Examples found in repository?
examples/closure_supplier_ops_demo.rs (line 53)
18fn main() {
19    println!("=== Closure Supplier Operations Demo ===\n");
20
21    // 1. FnMut closure using map
22    println!("1. FnMut closure using map:");
23    let mut counter = 0;
24    let mut mapped = (move || {
25        counter += 1;
26        counter
27    })
28    .map(|x| x * 2);
29
30    println!("   First call: {}", mapped.get());
31    println!("   Second call: {}\n", mapped.get());
32
33    // 2. FnMut closure using filter
34    println!("2. FnMut closure using filter:");
35    let mut counter2 = 0;
36    let mut filtered = (move || {
37        counter2 += 1;
38        counter2
39    })
40    .filter(|x| x % 2 == 0);
41
42    println!("   First call (odd number): {:?}", filtered.get());
43    println!("   Second call (even number): {:?}\n", filtered.get());
44
45    // 3. FnMut closure using memoize
46    println!("3. FnMut closure using memoize:");
47    let mut call_count = 0;
48    let mut memoized = (move || {
49        call_count += 1;
50        println!("   Underlying function called {} times", call_count);
51        42
52    })
53    .memoize();
54
55    println!("   First call: {}", memoized.get());
56    println!("   Second call: {}", memoized.get());
57    println!("   Third call: {}\n", memoized.get());
58
59    // 4. Fn closure using map (Fn also implements FnMut, so can use FnSupplierOps)
60    println!("4. Fn closure using map:");
61    let mut mapped_readonly = (|| 10).map(|x| x * 3).map(|x| x + 5);
62    println!("   Result: {}\n", mapped_readonly.get());
63
64    // 5. Fn closure using filter (Fn also implements FnMut, so can use FnSupplierOps)
65    println!("5. Fn closure using filter:");
66    let mut filtered_readonly = (|| 42).filter(|x| x % 2 == 0);
67    println!("   Filtered even number: {:?}\n", filtered_readonly.get());
68
69    // 6. Chained operations
70    println!("6. Chained operations:");
71    let mut counter3 = 0;
72    let mut chained = (move || {
73        counter3 += 1;
74        counter3
75    })
76    .map(|x| x * 2)
77    .filter(|x| *x > 5)
78    .map(|opt: Option<i32>| opt.unwrap_or(0));
79
80    println!("   First call: {}", chained.get()); // 2, filtered out
81    println!("   Second call: {}", chained.get()); // 4, filtered out
82    println!("   Third call: {}", chained.get()); // 6, passed
83    println!("   Fourth call: {}\n", chained.get()); // 8, passed
84
85    println!("=== Demo completed ===");
86}

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<T, F> FnSupplierOps<T> for F
where F: FnMut() -> T + Sized + 'static,