Skip to main content

consumer_fn_usage/
consumer_fn_usage.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//! Demonstrates how into_fn and to_fn are used with function parameters that accept closures
11
12use qubit_function::{
13    ArcConsumer,
14    BoxConsumer,
15    Consumer,
16    RcConsumer,
17};
18use std::cell::RefCell;
19use std::rc::Rc;
20use std::sync::{
21    Arc,
22    Mutex,
23};
24
25fn main() {
26    println!("=== Consumer into_fn/to_fn Usage Examples ===\n");
27
28    // Example 1: Using BoxConsumer::into_fn to pass to standard library's map
29    println!("1. BoxConsumer::into_fn used with Iterator::for_each");
30    let log = Arc::new(Mutex::new(Vec::new()));
31    let l = log.clone();
32    let consumer = BoxConsumer::new(move |x: &i32| {
33        l.lock().expect("mutex should not be poisoned").push(*x * 2);
34    });
35
36    // Convert consumer to closure and pass to for_each
37    [1, 2, 3, 4, 5].iter().for_each(consumer.into_fn());
38    println!(
39        "   Result: {:?}\n",
40        *log.lock().expect("mutex should not be poisoned")
41    );
42
43    // Example 2: Using ArcConsumer::to_fn can be used multiple times
44    println!("2. ArcConsumer::to_fn can be used multiple times");
45    let log2 = Arc::new(Mutex::new(Vec::new()));
46    let l2 = log2.clone();
47    let consumer2 = ArcConsumer::new(move |x: &i32| {
48        l2.lock()
49            .expect("mutex should not be poisoned")
50            .push(*x + 10);
51    });
52
53    // to_fn doesn't consume consumer, can be called multiple times
54    [1, 2, 3].iter().for_each(consumer2.to_fn());
55    println!(
56        "   First time: {:?}",
57        *log2.lock().expect("mutex should not be poisoned")
58    );
59
60    [4, 5].iter().for_each(consumer2.to_fn());
61    println!(
62        "   Second time: {:?}\n",
63        *log2.lock().expect("mutex should not be poisoned")
64    );
65
66    // Example 3: Using RcConsumer::to_fn
67    println!("3. RcConsumer::to_fn used for single-threaded scenarios");
68    let log3 = Rc::new(RefCell::new(Vec::new()));
69    let l3 = log3.clone();
70    let consumer3 = RcConsumer::new(move |x: &i32| {
71        l3.borrow_mut().push(*x * 3);
72    });
73
74    [1, 2, 3, 4].iter().for_each(consumer3.to_fn());
75    println!("   Result: {:?}\n", *log3.borrow());
76
77    // Example 4: Using in custom functions
78    println!("4. Using in custom functions");
79    fn process_items<F>(items: Vec<i32>, consumer: F)
80    where
81        F: FnMut(&i32),
82    {
83        items.iter().for_each(consumer);
84    }
85
86    let log4 = Arc::new(Mutex::new(Vec::new()));
87    let l4 = log4.clone();
88    let consumer4 = BoxConsumer::new(move |x: &i32| {
89        l4.lock()
90            .expect("mutex should not be poisoned")
91            .push(*x * 5);
92    });
93
94    // Use into_fn to convert Consumer to closure and pass to function
95    process_items(vec![1, 2, 3], consumer4.into_fn());
96    println!(
97        "   Result: {:?}\n",
98        *log4.lock().expect("mutex should not be poisoned")
99    );
100
101    // Example 5: Using into_fn after chained operations
102    println!("5. Using into_fn after chained operations");
103    let log5 = Arc::new(Mutex::new(Vec::new()));
104    let l5 = log5.clone();
105    let l6 = log5.clone();
106
107    let chained = BoxConsumer::new(move |x: &i32| {
108        l5.lock()
109            .expect("mutex should not be poisoned")
110            .push(format!("A: {}", x));
111    })
112    .and_then(move |x: &i32| {
113        l6.lock()
114            .expect("mutex should not be poisoned")
115            .push(format!("B: {}", x));
116    });
117
118    [1, 2].iter().for_each(chained.into_fn());
119    println!(
120        "   Result: {:?}\n",
121        *log5.lock().expect("mutex should not be poisoned")
122    );
123
124    println!("=== Demo Complete ===");
125}