rust_overture/
combinig.rs1pub fn combining<Root, Value, NewValue>(
4 getter: impl Fn(&Root) -> Value + Clone + 'static,
5 combine: impl Fn(Value, Value) -> NewValue + Clone + 'static,
6) -> impl Fn(Value, &Root) -> NewValue
7where
8 Value: Clone,
9{
10 move |value: Value, root: &Root| {
11 let rhs = getter(root);
12 combine(value, rhs)
13 }
14}
15
16pub fn combining_mut<Root, Value>(
18 getter: impl Fn(&Root) -> Value + Clone + 'static,
19 combine: impl Fn(&mut Value, Value) + Clone + 'static,
20) -> impl Fn(&mut Value, &Root)
21where
22 Value: Clone,
23{
24 move |value: &mut Value, root: &Root| {
25 let rhs = getter(root);
26 combine(value, rhs);
27 }
28}
29
30pub fn their<Root, Value, NewValue>(
33 getter: impl Fn(&Root) -> Value + Clone + 'static,
34 combine: impl Fn(Value, Value) -> NewValue + Clone + 'static,
35) -> impl Fn(&Root, &Root) -> NewValue
36where
37 Value: Clone,
38{
39 move |a: &Root, b: &Root| {
40 let va = getter(a);
41 let vb = getter(b);
42 combine(va, vb)
43 }
44}
45
46pub fn their_cmp<Root, Value>(
48 getter: impl Fn(&Root) -> Value + Clone + 'static,
49) -> impl Fn(&Root, &Root) -> bool
50where
51 Value: Ord + Clone,
52 Root: Clone,
53{
54 their(getter, |a: Value, b: Value| a < b)
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[derive(Debug, Clone, PartialEq)]
62 struct User {
63 name: String,
64 age: u32,
65 }
66
67 #[test]
68 fn test_combining() {
69 let user = User {
70 name: "Alice".into(),
71 age: 30,
72 };
73 let f = combining(|u: &User| u.age, |a, b| a + b);
74 assert_eq!(f(10, &user), 40); }
76
77 #[test]
78 fn test_combining_mut() {
79 let user = User {
80 name: "Bob".into(),
81 age: 5,
82 };
83 let mut value = 10;
84 let f = combining_mut(|u: &User| u.age, |a: &mut u32, b: u32| *a += b);
85 f(&mut value, &user);
86 assert_eq!(value, 15);
87 }
88
89 #[test]
90 fn test_their() {
91 let alice = User {
92 name: "Alice".into(),
93 age: 20,
94 };
95 let bob = User {
96 name: "Bob".into(),
97 age: 25,
98 };
99
100 let cmp = their(|u: &User| u.age, |a, b| a.max(b));
101 assert_eq!(cmp(&alice, &bob), 25);
102 }
103
104 #[test]
105 fn test_their_cmp() {
106 let alice = User {
107 name: "Alice".into(),
108 age: 20,
109 };
110 let bob = User {
111 name: "Bob".into(),
112 age: 25,
113 };
114
115 let cmp = their_cmp(|u: &User| u.age);
116 assert_eq!(cmp(&alice, &bob), true); assert_eq!(cmp(&bob, &alice), false); }
119}