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!("   Result: {:?}\n", *log.lock().expect("mutex should not be poisoned"));
39
40    // Example 2: Using ArcConsumer::to_fn can be used multiple times
41    println!("2. ArcConsumer::to_fn can be used multiple times");
42    let log2 = Arc::new(Mutex::new(Vec::new()));
43    let l2 = log2.clone();
44    let consumer2 = ArcConsumer::new(move |x: &i32| {
45        l2.lock().expect("mutex should not be poisoned").push(*x + 10);
46    });
47
48    // to_fn doesn't consume consumer, can be called multiple times
49    [1, 2, 3].iter().for_each(consumer2.to_fn());
50    println!(
51        "   First time: {:?}",
52        *log2.lock().expect("mutex should not be poisoned")
53    );
54
55    [4, 5].iter().for_each(consumer2.to_fn());
56    println!(
57        "   Second time: {:?}\n",
58        *log2.lock().expect("mutex should not be poisoned")
59    );
60
61    // Example 3: Using RcConsumer::to_fn
62    println!("3. RcConsumer::to_fn used for single-threaded scenarios");
63    let log3 = Rc::new(RefCell::new(Vec::new()));
64    let l3 = log3.clone();
65    let consumer3 = RcConsumer::new(move |x: &i32| {
66        l3.borrow_mut().push(*x * 3);
67    });
68
69    [1, 2, 3, 4].iter().for_each(consumer3.to_fn());
70    println!("   Result: {:?}\n", *log3.borrow());
71
72    // Example 4: Using in custom functions
73    println!("4. Using in custom functions");
74    fn process_items<F>(items: Vec<i32>, consumer: F)
75    where
76        F: FnMut(&i32),
77    {
78        items.iter().for_each(consumer);
79    }
80
81    let log4 = Arc::new(Mutex::new(Vec::new()));
82    let l4 = log4.clone();
83    let consumer4 = BoxConsumer::new(move |x: &i32| {
84        l4.lock().expect("mutex should not be poisoned").push(*x * 5);
85    });
86
87    // Use into_fn to convert Consumer to closure and pass to function
88    process_items(vec![1, 2, 3], consumer4.into_fn());
89    println!("   Result: {:?}\n", *log4.lock().expect("mutex should not be poisoned"));
90
91    // Example 5: Using into_fn after chained operations
92    println!("5. Using into_fn after chained operations");
93    let log5 = Arc::new(Mutex::new(Vec::new()));
94    let l5 = log5.clone();
95    let l6 = log5.clone();
96
97    let chained = BoxConsumer::new(move |x: &i32| {
98        l5.lock()
99            .expect("mutex should not be poisoned")
100            .push(format!("A: {}", x));
101    })
102    .and_then(move |x: &i32| {
103        l6.lock()
104            .expect("mutex should not be poisoned")
105            .push(format!("B: {}", x));
106    });
107
108    [1, 2].iter().for_each(chained.into_fn());
109    println!("   Result: {:?}\n", *log5.lock().expect("mutex should not be poisoned"));
110
111    println!("=== Demo Complete ===");
112}