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§
Sourcefn map<U, M>(self, mapper: M) -> BoxSupplier<U>where
M: Mapper<T, U> + 'static,
U: 'static,
T: 'static,
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?
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}Sourcefn filter<P>(self, predicate: P) -> BoxSupplier<Option<T>>
fn filter<P>(self, predicate: P) -> BoxSupplier<Option<T>>
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 evenExamples found in repository?
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}Sourcefn zip<U>(self, other: BoxSupplier<U>) -> BoxSupplier<(T, U)>where
U: 'static,
T: 'static,
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"));Sourcefn memoize(self) -> BoxSupplier<T>where
T: Clone + 'static,
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 valueExamples found in repository?
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.