qubit-function 0.7.3

Common functional programming type aliases for Rust, providing Java-style functional interfaces
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
# Predicate 设计方案分析

## 概述

本文档从 Predicate(谓词)的本质语义出发,分析其主要用途和核心价值,探讨合理的设计方案。

Predicate 的核心功能是**判断一个值是否满足特定条件**,类似于 Java 中的 `Predicate<T>` 接口和 Rust 标准库中的 `Fn(&T) -> bool`。本文将深入分析为什么很多看似合理的设计实际上是过度设计,并提出简化且更符合语义的解决方案。

---

## 一、Predicate 的本质语义

### 1.1 什么是 Predicate?

**Predicate(谓词)的核心语义**:

> **判断一个值是否满足某个条件,返回布尔值。这是一个纯粹的"只读判断"操作,不应该有副作用。**

这类似于数学中的谓词逻辑:
- **判断条件**:读取值的属性,做出真假判断
-**无副作用**:不修改被判断的值
-**可重复性**:同样的输入应该得到同样的结果
-**确定性**:判断逻辑应该是确定的、可预测的

**对比其他函数式抽象**:

| 类型 | 输入 | 输出 | 修改输入? | 修改自己? | 典型用途 |
|------|------|------|-----------|-----------|---------|
| **Predicate** | `&T` | `bool` ||| 过滤、验证、条件判断 |
| **Consumer** | `&T` | `()` ||| 观察、日志、统计、累积 |
| **Function** | `&T` | `R` ||| 转换、映射、计算 |

**关键洞察**:
- Predicate 的语义是"判断",判断本身不应该改变任何东西
- 如果一个"谓词"在判断时会改变状态,那可能根本不应该叫谓词

### 1.2 Predicate 的主要用途

| 用途 | 描述 | 示例 |
|------|------|------|
| **过滤/筛选** | 配合 `filter()` 等迭代器方法 | `vec.into_iter().filter(predicate)` |
| **条件验证** | 表单验证、数据校验 | `validator.test(&user_input)` |
| **逻辑组合** | 构建复杂判断条件 | `is_adult.and(&has_license)` |
| **策略模式** | 将判断逻辑作为策略保存 | `rules.insert("age", predicate)` |
| **配置驱动** | 在配置中心保存验证规则 | `config.get_validator("email")` |

### 1.3 Predicate 的核心价值

**临时判断 vs 保存逻辑**:

```rust
// ❌ 不需要 Predicate:临时判断一次
if x > 0 && x % 2 == 0 {
    println!("positive and even");
}

// ✅ 需要 Predicate:保存判断逻辑以便复用
let is_valid = BoxPredicate::new(|x: &i32| *x > 0 && x % 2 == 0);
let result1 = values1.into_iter().filter(|x| is_valid.test(x));
let result2 = values2.into_iter().filter(|x| is_valid.test(x));
```

**Predicate 的价值在于**:
1. **保存判断逻辑**:将判断条件封装为可复用的对象
2. **延迟执行**:在需要的时候才执行判断
3. **逻辑组合**:通过 `and``or``not` 构建复杂条件
4. **简化接口**:作为类型约束提高代码可读性

---

## 二、核心设计决策

### 2.1 为什么不需要 PredicateOnce?❌

#### 语义矛盾

Predicate 的本质是"判断",而判断操作天然应该是**可重复的、无副作用的**。

```rust
// 🤔 这合理吗?
let is_positive = BoxPredicateOnce::new(|x: &i32| *x > 0);
assert!(is_positive.test_once(&5));  // 第一次判断
// is_positive 不能再用了!为什么判断"是否为正数"只能用一次?
```

**对比 Consumer**:
- `ConsumerOnce` 有意义:消费一个值,消费完就没了(如发送消息、关闭资源)
- `PredicateOnce` 困惑:判断一个值,判断完为什么谓词就没了?

#### 缺乏真实使用场景

所谓的"使用场景"都是牵强附会的:

1. **闭包捕获非克隆资源** - 这不是 Predicate 的典型场景,更像是特殊的资源管理
2. **类型系统表达性** - 为了表达而表达,不是真实需求
3. **延迟执行** - 直接用 `FnOnce` 闭包更简单

#### 与 PredicateMut 边界模糊

```rust
// PredicateMut 可以做 PredicateOnce 能做的一切
let mut pred = BoxPredicateMut::new(|x: &i32| *x > 0);
pred.test_mut(&5);   // 可以调用一次
pred.test_mut(&10);  // 也可以调用多次
pred.test_once(&15); // 最后消费掉
```

**结论**:`PredicateOnce` 的存在价值极低,是为了"完整性"而设计的,不是源于真实需求。应该**移除**。

---

### 2.2 为什么不需要 PredicateMut?🤔

#### 内部可变性足以解决所有"需要状态"的场景

所有看似需要 `&mut self` 的场景,都可以用内部可变性(Interior Mutability)更优雅地实现:

**场景 1:缓存机制**

```rust
// ❌ 使用 PredicateMut
let mut cache = HashMap::new();
let mut pred = BoxPredicateMut::new(move |x: &i32| {
    *cache.entry(*x).or_insert_with(|| expensive(*x))
});
pred.test_mut(&5);  // 用户必须写 mut

// ✅ 使用 Predicate + RefCell
let cache = RefCell::new(HashMap::new());
let pred = BoxPredicate::new(move |x: &i32| {
    *cache.borrow_mut().entry(*x).or_insert_with(|| expensive(*x))
});
pred.test(&5);  // 用户不需要 mut
```

**场景 2:计数器**

```rust
// ❌ 使用 PredicateMut
let mut count = 0;
let mut pred = BoxPredicateMut::new(move |x: &i32| {
    count += 1;
    *x > 0
});

// ✅ 使用 Predicate + Cell
let count = Cell::new(0);
let pred = BoxPredicate::new(move |x: &i32| {
    count.set(count.get() + 1);
    *x > 0
});
```

**场景 3:线程安全的状态**

```rust
// ❌ 使用 ArcPredicateMut
let counter = Arc::new(Mutex::new(0));
let mut pred = ArcPredicateMut::new(move |x: &i32| {
    let mut count = counter.lock().unwrap();
    *count += 1;
    *x > 0
});

// ✅ 使用 ArcPredicate + Mutex(一样的实现)
let counter = Arc::new(Mutex::new(0));
let pred = ArcPredicate::new(move |x: &i32| {
    let mut count = counter.lock().unwrap();
    *count += 1;
    *x > 0
});
```

#### 为什么内部可变性更好?

| 特性 | PredicateMut (`&mut self`) | Predicate + RefCell (`&self`) |
|------|---------------------------|-------------------------------|
| **用户代码** | `let mut pred = ...` | `let pred = ...` |
| **调用方式** | `pred.test_mut(&x)` | `pred.test(&x)` |
| **语义** | "这个谓词会改变" ❌ | "这个谓词是判断"(内部优化)✅ |
| **灵活性** | 不能在不可变上下文使用 | 可以在任何地方使用 |
| **实现复杂度** | 需要额外的 trait | 统一使用 Predicate |

#### 对比标准库的设计

Rust 标准库大量使用内部可变性来隐藏实现细节:

```rust
// Arc::clone 内部修改引用计数,但接口是 &self
pub fn clone(&self) -> Self {
    // 原子增加引用计数(内部可变性)
}

// RefCell 提供内部可变性
let cell = RefCell::new(5);
let borrowed = cell.borrow_mut();  // &self → &mut T
```

**结论**:`PredicateMut` 是不必要的复杂度,应该**移除**。所有需要状态的场景用内部可变性解决。

---

### 2.3 简化后的核心设计

基于以上分析,Predicate 模块只需要:

```rust
/// 谓词 - 判断值是否满足条件
pub trait Predicate<T> {
    /// 测试值是否满足条件
    ///
    /// 使用 &self,不会改变谓词本身(从用户角度)。
    /// 如果需要内部状态(如缓存),使用 RefCell、Cell 或 Mutex。
    fn test(&self, value: &T) -> bool;

    // 类型转换方法
    fn into_box(self) -> BoxPredicate<T> where ...;
    fn into_rc(self) -> RcPredicate<T> where ...;
    fn into_arc(self) -> ArcPredicate<T> where ...;
}
```

**就这一个 trait!** 简单、清晰、符合语义。

---

## 三、实现方案对比

### 方案一:类型别名 + 静态组合方法

**核心思路**:

```rust
pub type Predicate<T> = Box<dyn Fn(&T) -> bool>;
pub type ArcPredicate<T> = Arc<dyn Fn(&T) -> bool + Send + Sync>;

pub struct Predicates;
impl Predicates {
    pub fn and<T>(first: ..., second: ...) -> Predicate<T> { ... }
    pub fn or<T>(first: ..., second: ...) -> Predicate<T> { ... }
}
```

**优点**:
- **极简 API**:直接调用 `pred(&value)`
-**零心智负担**:类型别名完全透明
-**与标准库完美集成**:可直接用于 `filter` 等方法
-**实现简单**:代码量少,易于理解

**缺点**:
- **无法扩展**:不能添加字段、实现 trait
-**类型区分度低**:与 `Box<dyn Fn>` 等价
-**无法实现方法链**:只能嵌套调用
-**需要维护多套 API**:Predicate、ArcPredicate、RcPredicate 分别有工具类

**适用场景**:快速原型、简单应用、追求极简 API

---

### 方案二:Struct 封装 + 实例方法

**核心思路**:

```rust
pub struct Predicate<T> {
    inner: Box<dyn Fn(&T) -> bool>,
    name: Option<String>,  // 可添加元数据
}

impl<T> Predicate<T> {
    pub fn test(&self, value: &T) -> bool { ... }
    pub fn and(self, other: ...) -> Self { ... }  // 消耗 self
    pub fn or(self, other: ...) -> Self { ... }
}

pub struct ArcPredicate<T> {
    inner: Arc<dyn Fn(&T) -> bool + Send + Sync>,
    name: Option<String>,
}
// 类似实现...
```

**优点**:
- **优雅的方法链**`.and().or().not()` 流式调用
-**强大的扩展性**:可添加字段、实现 trait
-**类型安全**:独立的类型,语义清晰

**缺点**:
- **无法直接调用**:必须 `pred.test(&value)`
-**需要多个独立实现**:Predicate、ArcPredicate、RcPredicate 代码重复
-**所有权问题**:Box 版本的方法链消耗 self,Arc 版本需要显式 clone

**适用场景**:需要元数据、需要方法链、面向对象风格

---

### 方案三:Trait 抽象 + 多种实现 ⭐(推荐)

**核心思路**:

```rust
// 1. 统一的 Predicate trait(最小化)
pub trait Predicate<T> {
    fn test(&self, value: &T) -> bool;
    // 只有 test 和 into_* 转换方法,没有逻辑组合
}

// 2. 为闭包实现 Predicate
impl<T, F> Predicate<T> for F where F: Fn(&T) -> bool {
    fn test(&self, value: &T) -> bool { self(value) }
}

// 3. 扩展 trait 为闭包提供组合方法
pub trait FnPredicateOps<T>: Fn(&T) -> bool {
    fn and<P>(self, other: P) -> BoxPredicate<T> { ... }
    fn or<P>(self, other: P) -> BoxPredicate<T> { ... }
}

// 4. 三种具体实现
pub struct BoxPredicate<T> { /* Box<dyn Fn> */ }
impl<T> BoxPredicate<T> {
    pub fn and<P>(self, other: P) -> BoxPredicate<T> { ... }  // 消耗 self
}

pub struct ArcPredicate<T> { /* Arc<dyn Fn + Send + Sync> */ }
impl<T> ArcPredicate<T> {
    pub fn and(&self, other: &ArcPredicate<T>) -> ArcPredicate<T> { ... }  // 借用 &self
}

pub struct RcPredicate<T> { /* Rc<dyn Fn> */ }
impl<T> RcPredicate<T> {
    pub fn and(&self, other: &RcPredicate<T>) -> RcPredicate<T> { ... }  // 借用 &self
}
```

**优点**:
- **统一的 trait 接口**:所有类型实现同一个 `Predicate<T>`
-**语义极其清晰**`BoxPredicate``ArcPredicate``RcPredicate` 名称即文档
-**完整的所有权模型**:Box(单一)、Arc(共享+线程安全)、Rc(共享+单线程)
-**类型保持**`ArcPredicate.and()` 返回 `ArcPredicate`,保持可克隆特性
-**优雅的 API**:Arc/Rc 使用 `&self`,无需显式 clone
-**最强扩展性**:可添加新类型、字段、trait
-**与 Rust 标准库一致**:类似 Box/Arc/Rc 智能指针的设计

**缺点**:
- **无法直接调用**:仍然需要 `.test()`
-**学习成本略高**:需要理解三种实现的区别
-**实现成本高**:需要为三个 struct 分别实现

**适用场景**:库开发、大型项目、长期维护、多场景支持

---

## 四、三种方案对比总结

| 特性 | 方案一:类型别名 | 方案二:Struct 封装 | 方案三:Trait + 多实现 ⭐ |
|:---|:---:|:---:|:---:|
| **调用方式** | `pred(&x)`| `pred.test(&x)` | `pred.test(&x)` |
| **语义清晰度** | 🟡 中等 | 🟢 好 | 🟢 **极好**|
| **统一接口** | ❌ 多套独立 API | ❌ 多个独立 struct |**统一 trait**|
| **所有权模型** | Box + Arc(两种)| Box + Arc(两种)| Box + Arc + Rc(三种)✅ |
| **方法链** | ❌ 只能嵌套 | ✅ 支持 |**支持(且类型保持)**|
| **扩展性** | ❌ 无法扩展 | ✅ 可扩展 |**极易扩展** |
| **代码简洁度** |**极简** | 🟡 中等 | 🟡 略复杂 |
| **学习成本** |**最低** | 🟡 中等 | 🟡 略高 |
| **维护成本** | 🟡 中等 | 🟡 中等 |**低(架构清晰)** |
| **与标准库一致** | 🟡 中等 | 🟡 中等 |**完美**|

---

## 五、最终推荐设计

### 5.1 核心架构

```rust
// ============================================================================
// 1. 最小化的 Predicate trait
// ============================================================================

/// 谓词 - 判断值是否满足条件
pub trait Predicate<T> {
    /// 测试值是否满足条件
    fn test(&self, value: &T) -> bool;

    // 类型转换方法
    fn into_box(self) -> BoxPredicate<T> where Self: Sized + 'static, T: 'static;
    fn into_rc(self) -> RcPredicate<T> where Self: Sized + 'static, T: 'static;
    fn into_arc(self) -> ArcPredicate<T> where Self: Sized + Send + Sync + 'static, T: Send + Sync + 'static;
}

// ============================================================================
// 2. 为闭包提供扩展能力
// ============================================================================

/// 为闭包实现 Predicate trait
impl<T, F> Predicate<T> for F where F: Fn(&T) -> bool {
    fn test(&self, value: &T) -> bool { self(value) }
    // ...
}

/// 为闭包提供组合方法的扩展 trait
pub trait FnPredicateOps<T>: Fn(&T) -> bool + Sized {
    fn and<P>(self, other: P) -> BoxPredicate<T> { ... }
    fn or<P>(self, other: P) -> BoxPredicate<T> { ... }
    fn not(self) -> BoxPredicate<T> { ... }
}

// ============================================================================
// 3. 三种具体实现
// ============================================================================

/// Box 实现 - 单一所有权,消耗 self
pub struct BoxPredicate<T> {
    function: Box<dyn Fn(&T) -> bool>,
    name: Option<String>,
}

impl<T> BoxPredicate<T> {
    pub fn and<P>(self, other: P) -> BoxPredicate<T> { ... }  // 消耗 self
    pub fn or<P>(self, other: P) -> BoxPredicate<T> { ... }
    pub fn not(self) -> BoxPredicate<T> { ... }
}

/// Arc 实现 - 线程安全共享,借用 &self
pub struct ArcPredicate<T> {
    function: Arc<dyn Fn(&T) -> bool + Send + Sync>,
    name: Option<String>,
}

impl<T> ArcPredicate<T> {
    pub fn and(&self, other: &ArcPredicate<T>) -> ArcPredicate<T> { ... }  // 借用 &self
    pub fn or(&self, other: &ArcPredicate<T>) -> ArcPredicate<T> { ... }
    pub fn not(&self) -> ArcPredicate<T> { ... }

    // 提供 to_* 方法(不消耗 self)
    pub fn to_box(&self) -> BoxPredicate<T> { ... }
    pub fn to_rc(&self) -> RcPredicate<T> { ... }
}

/// Rc 实现 - 单线程共享,借用 &self
pub struct RcPredicate<T> {
    function: Rc<dyn Fn(&T) -> bool>,
    name: Option<String>,
}

impl<T> RcPredicate<T> {
    pub fn and(&self, other: &RcPredicate<T>) -> RcPredicate<T> { ... }  // 借用 &self
    pub fn or(&self, other: &RcPredicate<T>) -> RcPredicate<T> { ... }
    pub fn not(&self) -> RcPredicate<T> { ... }

    // 提供 to_* 方法(不消耗 self)
    pub fn to_box(&self) -> BoxPredicate<T> { ... }
}
```

### 5.2 使用示例

```rust
// 闭包自动实现 Predicate
let is_positive = |x: &i32| *x > 0;
assert!(is_positive.test(&5));

// 闭包组合返回 BoxPredicate
let combined = is_positive.and(|x: &i32| x % 2 == 0);
assert!(combined.test(&4));

// BoxPredicate - 一次性使用
let pred = BoxPredicate::new(|x: &i32| *x > 0)
    .and(|x| x % 2 == 0);

// ArcPredicate - 多线程共享,无需显式 clone
let arc_pred = ArcPredicate::new(|x: &i32| *x > 0);
let combined = arc_pred.and(&ArcPredicate::new(|x| x % 2 == 0));
assert!(arc_pred.test(&5));  // 原谓词仍可用

// RcPredicate - 单线程复用,性能更好
let rc_pred = RcPredicate::new(|x: &i32| *x > 0);
let combined1 = rc_pred.and(&RcPredicate::new(|x| x % 2 == 0));
let combined2 = rc_pred.or(&RcPredicate::new(|x| *x > 100));

// 内部可变性实现缓存
use std::cell::RefCell;
let cache = RefCell::new(HashMap::new());
let cached = BoxPredicate::new(move |x: &i32| {
    *cache.borrow_mut().entry(*x).or_insert_with(|| expensive(*x))
});
cached.test(&5);  // 不需要 mut
```

### 5.3 类型选择指南

| 需求 | 推荐类型 | 理由 |
|------|---------|------|
| 一次性使用 | `BoxPredicate` | 单一所有权,无开销 |
| 多线程共享 | `ArcPredicate` | 线程安全,可克隆 |
| 单线程复用 | `RcPredicate` | 无原子操作,性能更好 |
| 需要内部状态 | 任意类型 + RefCell/Cell/Mutex | 内部可变性 |

---

## 六、总结

### 6.1 核心设计原则

1. **Predicate 是纯判断**:不修改输入,不修改自己(从语义上)
2. **只需要一个 Predicate trait**:使用 `&self`,简单清晰
3. **移除 PredicateOnce**:违背语义,缺乏真实场景
4. **移除 PredicateMut**:内部可变性完全够用
5. **提供三种实现**:Box/Arc/Rc 覆盖所有所有权场景
6. **类型名称语义明确**:BoxPredicate、ArcPredicate、RcPredicate

### 6.2 为什么这个设计最好?

**与过度设计的对比**:

| | 过度设计(当前) | 简化设计(推荐) |
|---|---|---|
| **Trait 数量** | 3 个(Predicate、PredicateMut、PredicateOnce)| 1 个(Predicate)✅ |
| **核心语义** | 混乱(可变、一次性)| 清晰(纯判断)✅ |
| **用户心智负担** | 高(何时用哪个?)| 低(只有一种)✅ |
| **状态管理** | 需要 `&mut self` | 内部可变性 ✅ |
| **API 一致性** | 多套方法(test, test_mut, test_once)| 统一的 test ✅ |

**与 Consumer 设计的一致性**:

- Consumer **可以**修改自己(累积、计数是核心用途)→ ConsumerMut 合理
- Predicate **不应该**修改自己(纯判断是核心语义)→ PredicateMut 不合理

### 6.3 最终结论

对于 `qubit-function` 这样的库项目:

1. **采用方案三**:Trait + 多种实现
2. **简化为单一 Predicate trait**:移除 Mut 和 Once 变体
3. **提供三种实现**:BoxPredicate、ArcPredicate、RcPredicate
4. **使用内部可变性**:需要状态时用 RefCell/Cell/Mutex
5. **文档说明最佳实践**:指导用户何时使用哪种类型

这个设计:
- **更简单**:只有一个核心 trait
-**更符合语义**:Predicate 就是判断,不应该"改变"
-**更灵活**:不需要 `mut` 可以在更多地方使用
-**与 Rust 习惯一致**:标准库大量使用内部可变性模式
-**长期可维护**:架构清晰,语义明确

**这是一个经过深思熟虑、去除过度设计、回归本质的优雅方案。**