Skip to main content

predicate_fn_mut_demo/
predicate_fn_mut_demo.rs

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