narust_158/entity/linkages/t_link.rs
1//! 作为「词项链」与「任务链」共有的特征基础存在
2
3use crate::symbols::*;
4use serde::{Deserialize, Serialize};
5use std::ops::{Deref, DerefMut};
6
7/// 基于枚举的「链接类型」
8/// * 📌【2024-06-04 19:35:12】拨乱反正:此处的「类型名」均为「从自身向目标」视角下「目标相对自身」的类型
9/// * 📄目标是自身的元素⇒COMPONENT「元素」链接
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
11pub enum TLinkType {
12 /// From C, targeted to "SELF" C; TaskLink only
13 /// * 🚩【2024-06-22 00:26:43】避嫌Rust的`Self`关键字
14 SELF,
15 /// From (&&, A, C), targeted to "COMPONENT" C
16 Component,
17 /// From C, targeted to "COMPOUND" (&&, A, C)
18 Compound,
19 /// From <C --> A>, targeted to "COMPONENT_STATEMENT" C
20 ComponentStatement,
21 /// From C, targeted to "COMPOUND_STATEMENT" <C --> A>
22 CompoundStatement,
23 /// From <(&&, C, B) ==> A>, targeted to "COMPONENT_CONDITION" C
24 ComponentCondition,
25 /// From C, targeted to "COMPOUND_CONDITION" <(&&, C, B) ==> A>
26 CompoundCondition,
27 /// From C, targeted to "TRANSFORM" <(*, C, B) --> A>; TaskLink only
28 Transform,
29}
30
31impl TLinkType {
32 /// 🆕获取「链接类型」的「排序」,即原OpenNARS中的编号
33 /// * 📝【2024-06-22 00:32:57】不建议在结构体定义之处附带数值
34 /// * 📌附带的数值只能是[`isize`]类型
35 /// * ❌无法在【不增加维护成本】的同时转换到[`usize`]类型
36 pub fn to_order(&self) -> usize {
37 use TLinkType::*;
38 match self {
39 SELF => 0,
40 Component => 1,
41 Compound => 2,
42 ComponentStatement => 3,
43 CompoundStatement => 4,
44 ComponentCondition => 5,
45 CompoundCondition => 6,
46 Transform => 8,
47 }
48 }
49
50 /// 🆕判断一个「T链接类型」是否为「从复合词项链接到元素」
51 pub fn is_to_component(&self) -> bool {
52 use TLinkType::*;
53 // 1 3 5
54 matches!(self, Component | ComponentStatement | ComponentCondition)
55 }
56
57 /// 🆕判断一个「T链接类型」是否为「从元素链接到复合词项」
58 pub fn is_to_compound(&self) -> bool {
59 use TLinkType::*;
60 // 2 4 6
61 // * 🚩【2024-06-04 18:25:26】目前不包括TRANSFORM
62 matches!(self, Compound | CompoundStatement | CompoundCondition)
63 }
64
65 /// 🆕从「元素→整体」变成「整体→元素」
66 /// * 🚩「自元素到整体」⇒「自整体到元素」
67 /// * 📌【2024-06-04 19:51:48】目前只在「元素→整体」⇒「整体→元素」的过程中调用
68 /// * ✅【2024-06-22 00:38:55】此处使用「默认返回自身」兼容
69 pub fn try_point_to_component(self) -> Self {
70 // // * 🚩改版中只会发生在`COMPOUND`变种中
71 // debug_assert!(
72 // matches!(self, Compound | CompoundStatement | CompoundCondition),
73 // "原始值 {self:?} 并非指向复合词项"
74 // );
75 use TLinkType::*;
76 match self {
77 Compound => Component,
78 ComponentStatement => ComponentStatement,
79 CompoundStatement => ComponentStatement,
80 CompoundCondition => ComponentCondition,
81 // * 🚩其它的默认逻辑:返回自身 | 这也是其所用之处的默认情况
82 // ! 🤦【2024-08-05 01:44:56】血泪教训:别盲目兼容
83 // * 📝不然这「默认兼容情况」就可能有「漏网之鱼」
84 _ => panic!("不支持的转换:{self:?}"),
85 }
86 }
87}
88
89/// 🆕任务链与词项链共有的「T链接」
90/// * 🚩【2024-06-01 20:56:49】现在不再基于[`Item`],交由后续「词项链」「任务链」「词项链模板」自由组合
91pub trait TLink<Target> {
92 /// 链接所指目标
93 /// * ⚠️此处不能只是引用:可能会有「共享引用代理」的情况
94 /// * 🚩【2024-06-22 12:13:37】目前仿照[`crate::global::RC`]的签名,改为「可解引用的类型」
95 /// * ✅此举可实现「引用」和「共享引用代理」的兼容
96 fn target<'r, 's: 'r>(&'s self) -> impl Deref<Target = Target> + 'r;
97
98 /// 目标的可变引用
99 /// * ⚠️此处不能只是引用:可能会有「共享引用代理」的情况
100 /// * 🚩【2024-06-22 12:13:37】目前仿照[`crate::global::RC`]的签名,改为「可解引用的类型」
101 /// * ✅此举可实现「引用」和「共享引用代理」的兼容
102 /// * 🎯在「任务链」中需要
103 /// * 📄推理上下文中仅靠「任务链」获取「当前任务」
104 fn target_mut<'r, 's: 'r>(&'s mut self) -> impl DerefMut<Target = Target> + 'r;
105
106 /// 链接类型
107 /// * 📌【2024-06-22 00:41:22】[`TLinkType`]实现了[`Copy`],所以直接传出所有权
108 fn link_type(&self) -> TLinkType;
109
110 /// 获取链接的「索引」,指向具体词项的位置
111 /// * 🎯表示「链接起点」与「链接目标」词项的位置关系
112 /// * 📌创建后不再改变(只读)
113 fn indexes(&self) -> &[usize];
114
115 /// Set the key of the link
116 /// * 📝原`setKey`就是「根据现有信息计算出key,并最终给自身key赋值」的功能
117 /// * 🚩【2024-05-30 19:06:30】现在不再有副作用,仅返回key让调用方自行决定
118 /// * 📌原`setKey()`要变成`this.key = generateKey(this.type, this.index)`
119 /// * 🚩目前不再使用继承机制,而是在各个实现中使用特化的函数
120 #[doc(alias = "generate_key")]
121 fn generate_key_base(link_type: TLinkType, indexes: &[usize]) -> String {
122 // * 🚩先添加左右括弧,分「向元素」和「向整体」表示
123 // * 📌格式:自身 - 目标 | "_"即「元素」
124 // * 📝 向元素: 整体 "@(【索引】)_" 元素
125 // * 📝 向整体: 元素 "_@(【索引】)" 整体
126 let [at1, at2] = match link_type.is_to_component() {
127 true => TO_COMPONENT,
128 false => TO_COMPOUND,
129 };
130 let mut inner = format!("T{}", link_type.to_order());
131 for index in indexes {
132 inner += "-";
133 inner += &(index + 1).to_string();
134 }
135 format!("{at1}{inner}{at2}")
136 }
137
138 /// Get one index by level
139 fn get_index(&self, index: usize) -> Option<&usize> {
140 self.indexes().get(index)
141 }
142
143 /// 快速假定性获取索引
144 /// * 🎯假定在界内;若在界外,则panic
145 fn index(&self, index: usize) -> usize {
146 self.indexes()[index]
147 }
148}