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(
49 getter: impl Fn(&Root) -> Value + Clone + 'static,
50) -> impl Fn(&Root, &Root) -> bool
51where
52 Value: Ord + Clone,
53 Root: Clone
54
55{
56 their(getter, |a: Value, b: Value| a < b)
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[derive(Debug, Clone, PartialEq)]
64 struct User {
65 name: String,
66 age: u32,
67 }
68
69 #[test]
70 fn test_combining() {
71 let user = User { name: "Alice".into(), age: 30 };
72 let f = combining(|u: &User| u.age, |a, b| a + b);
73 assert_eq!(f(10, &user), 40); }
75
76 #[test]
77 fn test_combining_mut() {
78 let user = User { name: "Bob".into(), age: 5 };
79 let mut value = 10;
80 let f = combining_mut(|u: &User| u.age, |a: &mut u32, b: u32| *a += b);
81 f(&mut value, &user);
82 assert_eq!(value, 15);
83 }
84
85 #[test]
86 fn test_their() {
87 let alice = User { name: "Alice".into(), age: 20 };
88 let bob = User { name: "Bob".into(), age: 25 };
89
90 let cmp = their(|u: &User| u.age, |a, b| a.max(b));
91 assert_eq!(cmp(&alice, &bob), 25);
92 }
93
94 #[test]
95 fn test_their_cmp() {
96 let alice = User { name: "Alice".into(), age: 20 };
97 let bob = User { name: "Bob".into(), age: 25 };
98
99 let cmp = their_cmp(|u: &User| u.age);
100 assert_eq!(cmp(&alice, &bob), true); assert_eq!(cmp(&bob, &alice), false); }
103}