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}