Skip to main content

predicate_fn_mut_demo/
predicate_fn_mut_demo.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026.
4 *    Haixing Hu, Qubit Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9
10//! Demonstrates how Predicate's into_fn/to_fn methods can be used in scenarios requiring FnMut
11
12use qubit_function::{
13    ArcPredicate,
14    BoxPredicate,
15    Predicate,
16    RcPredicate,
17};
18
19fn main() {
20    println!("=== Demonstrating Predicate compatibility with FnMut ===\n");
21
22    demo_with_iterator_filter();
23    demo_with_vec_retain();
24    demo_with_generic_function();
25    demo_thread_safe();
26}
27
28/// Demonstrates usage with Iterator::filter (filter requires FnMut)
29fn demo_with_iterator_filter() {
30    println!("1. Using Iterator::filter");
31
32    let pred = BoxPredicate::new(|x: &i32| *x > 0);
33    let numbers = vec![-2, -1, 0, 1, 2, 3];
34    let positives: Vec<_> = numbers.iter().copied().filter(pred.into_fn()).collect();
35    println!("   Original data: {:?}", numbers);
36    println!("   Filtered result: {:?}", positives);
37    assert_eq!(positives, vec![1, 2, 3]);
38    println!("   ✓ BoxPredicate::into_fn() can be used in filter\n");
39}
40
41/// Demonstrates usage with Vec::retain (retain requires FnMut)
42fn demo_with_vec_retain() {
43    println!("2. Using Vec::retain");
44
45    // RcPredicate example
46    let pred = RcPredicate::new(|x: &i32| *x % 2 == 0);
47    let mut numbers = vec![1, 2, 3, 4, 5, 6];
48    println!("   Original data: {:?}", numbers);
49    numbers.retain(pred.to_fn());
50    println!("   Retained even numbers: {:?}", numbers);
51    assert_eq!(numbers, vec![2, 4, 6]);
52
53    // Original predicate is still available
54    assert!(pred.test(&10));
55    println!("   ✓ RcPredicate::to_fn() can be used in retain");
56    println!("   ✓ Original predicate is still available\n");
57}
58
59/// Demonstrates usage with generic functions that require FnMut
60fn demo_with_generic_function() {
61    println!("3. Using generic functions (requires FnMut)");
62
63    fn count_matching<F>(items: &[i32], mut predicate: F) -> usize
64    where
65        F: FnMut(&i32) -> bool,
66    {
67        items.iter().filter(|x| predicate(x)).count()
68    }
69
70    let pred = RcPredicate::new(|x: &i32| *x > 10);
71    let count1 = count_matching(&[5, 15, 8, 20], pred.to_fn());
72    println!("   First call: count = {}", count1);
73    assert_eq!(count1, 2);
74
75    // Original predicate can be reused
76    let count2 = count_matching(&[12, 3, 18], pred.to_fn());
77    println!("   Second call: count = {}", count2);
78    assert_eq!(count2, 2);
79
80    println!("   ✓ RcPredicate::to_fn() can be passed to generic functions requiring FnMut");
81    println!("   ✓ Original predicate can be converted and used multiple times\n");
82}
83
84/// Demonstrates thread-safe usage
85fn demo_thread_safe() {
86    println!("4. Thread-safe usage");
87
88    let pred = ArcPredicate::new(|x: &i32| *x > 0);
89    // clone and convert into a 'static closure so it can be moved to another thread
90    let closure = pred.clone().into_fn();
91
92    // Closure can be passed between threads
93    let handle = std::thread::spawn(move || {
94        let numbers = [-2, -1, 0, 1, 2, 3];
95        numbers.iter().copied().filter(closure).count()
96    });
97
98    let count = handle.join().unwrap();
99    println!("   Filtered result count in thread: {}", count);
100    assert_eq!(count, 3);
101
102    // Original predicate is still available
103    assert!(pred.test(&5));
104    println!("   ✓ ArcPredicate::to_fn() returns a thread-safe closure");
105    println!("   ✓ Original predicate is still available in main thread\n");
106}