study_rust_example/iterator_closure/
closure_study.rs

1use std::time::Duration;
2
3#[derive(Debug, Clone, Copy)]
4enum ShirtColor {
5    Blue,
6    Red,
7}
8
9struct Inventory {
10    shirts: Vec<ShirtColor>,
11}
12
13impl Inventory {
14    fn giveaway(&self, user_preference: Option<ShirtColor>) -> ShirtColor {
15        // Option<T> 上的 unwrap_or_else 方法由标准库定义
16        // 它需要一个参数:一个不带任何参数的闭包,返回一个值 T (与存储在 Option<T> 的 Some 变体中的类型相同
17        // 如果 Option<T> 是 Some 变体,则 unwrap_or_else 返回 Some 中的值。如果 Option<T> 是 None 变体,则 unwrap_or_else 调用闭包并返回闭包返回的值
18        // 闭包捕获对 self Inventory 实例的不可变引用,并将其与我们指定的代码一起传递给 unwrap_or_else 方法
19        user_preference.unwrap_or_else(|| self.most_stocked())
20    }
21
22    fn most_stocked(&self) -> ShirtColor {
23        let mut num_red = 0;
24        let mut num_blue = 0;
25        for color in &self.shirts {
26            match color {
27                ShirtColor::Blue => num_blue += 1,
28                ShirtColor::Red => num_red += 1,
29            }
30        }
31        if num_blue > num_red {
32            ShirtColor::Blue
33        } else {
34            ShirtColor::Red
35        }
36    }
37}
38
39fn inventory_usage() {
40    // 初始化库存
41    let store = Inventory {
42        shirts: vec![
43            ShirtColor::Blue,
44            ShirtColor::Red,
45            ShirtColor::Blue,
46            ShirtColor::Red,
47            ShirtColor::Blue,
48        ],
49    };
50    let user_pref1 = Some(ShirtColor::Red);
51    let giveaway1 = store.giveaway(user_pref1);
52    println!(
53        "The user with preference {:?} gets {:?}",
54        user_pref1, giveaway1
55    );
56    let user_pref2 = None;
57    let giveaway2 = store.giveaway(user_pref2);
58    println!(
59        "The user with preference {:?} gets {:?}",
60        user_pref2, giveaway2
61    );
62}
63
64fn example_closures_study() {
65    let example_closures = |x| x;
66    let s = example_closures(String::from("closures."));
67    // error[E0308]: mismatched types, 前面的调用使得推断了上面x的类型为String
68    // let n = example_closures(5);
69}
70
71fn capture_immut_reference() {
72    let list = vec![2, 433, 23];
73    println!("capture_immut_reference Before define closure {:?}", list);
74    let only_borrows = || println!("From closures: {:?}", list);
75    println!(
76        "capture_immut_reference before calling only_borrows closures: {:?}",
77        list
78    );
79    only_borrows();
80    println!(
81        "capture_immut_reference after calling only_borrows closures: {:?}",
82        list
83    );
84}
85
86fn capture_mut_reference() {
87    let mut list = vec![2, 433, 23];
88    println!("capture_mut_reference Before define closure {:?}", list);
89    let mut only_borrows = || list.push(32);
90    // 可变借用存在的时候不能进行不可变的借用
91    // println!("capture_immut_reference before calling only_borrows closures: {:?}", list);
92    only_borrows();
93    println!(
94        "capture_mut_reference after calling only_borrows closures: {:?}",
95        list
96    );
97}
98
99fn move_ownership_to_closuer() {
100    let list = vec![12, 43, 56];
101    println!(
102        "move_ownership_to_closuer before define closure, {:?}",
103        list
104    );
105    // 不添加move的话:error[E0373]: closure may outlive the current function, but it borrows `list`, which is owned by the current function
106    // 新线程可能会在主线程的其余部分完成之前完成,或者主线程可能会先完成。如果主线程保持 list 的所有权,但在新线程结束并删除 list 之前结束,则线程中的不可变引用将无效。
107    // 因此,编译器要求将 list 移至新线程的闭包中,以便引用有效
108    std::thread::spawn(move || println!("move_ownership_to_closuer from thread: {:?}", list))
109        .join()
110        .unwrap();
111}
112
113#[derive(Debug)]
114struct Rectangle {
115    width: u32,
116    height: u32,
117}
118
119fn fn_trait_closures() {
120    let mut list = [
121        Rectangle {
122            width: 10,
123            height: 1,
124        },
125        Rectangle {
126            width: 3,
127            height: 5,
128        },
129        Rectangle {
130            width: 7,
131            height: 12,
132        },
133    ];
134    list.sort_by_key(|r| r.width);
135    /*let mut sort_operations = vec![];
136    let value = String::from("by key called.");
137    list.sort_by_key(
138        |r|  {
139            // error[E0507]: cannot move out of `value`, a captured variable in an `FnMut` closure,解决方式添加引用
140            // 但是为什么输出4次字符串“by key called”?排序的次数?
141            sort_operations.push(value);
142            r.width
143        }
144    );
145     println!("sort operations: {:?}", sort_operations);
146    */
147    let mut num = 0;
148    list.sort_by_key(|r| {
149        num += 1;
150        r.width
151    });
152    println!("num: {num}");
153    println!("{:#?}", list);
154}
155
156pub fn closures_related_usage() {
157    inventory_usage();
158    let expensive_closures = |num: u32| -> u32 {
159        println!("caculating slowly...");
160        std::thread::sleep(Duration::from_secs(2));
161        return num;
162    };
163    let result = expensive_closures(32);
164    println!("expensive_closures result {result}");
165    capture_immut_reference();
166    capture_mut_reference();
167    move_ownership_to_closuer();
168    fn_trait_closures();
169}