📝 docs(tsl): expand syntax operator and object coverage

This commit is contained in:
csh 2026-06-10 15:25:42 +08:00
parent 540b3c0a1b
commit c0c2ffb6eb
6 changed files with 715 additions and 50 deletions

View File

@ -6,11 +6,11 @@
是否含不可照写反例:是
遇到不确定时:先按本页表格和专题入口继续判断;[03_values_and_literals.md](03_values_and_literals.md)、[04_variables_and_constants.md](04_variables_and_constants.md)、[05_functions_and_calls.md](05_functions_and_calls.md)、[07_control_flow.md](07_control_flow.md)、[08_objects_and_classes.md](08_objects_and_classes.md)、[12_matrix_and_collections.md](12_matrix_and_collections.md)、[16_lexical_structure_and_compile_options.md](16_lexical_structure_and_compile_options.md)、[11_pitfalls.md](11_pitfalls.md);仍不命中时回到语法路由中心 [index.md](index.md);如果问题已经超出语法层,回到 TSL 总入口 [../index.md](../index.md)
这一篇集中放语言级表达式与运算符。智能体写代码时,只使用本页和对应专题页已经本页明确的表达式事实,不要把其他语言或外部资料里的运算符习惯直接搬进 TSL。
这一篇集中放语言级表达式与运算符。智能体写代码时,只使用本页和对应专题页已经明确的表达式事实,不要把其他语言或外部资料里的运算符习惯直接搬进 TSL。
## 本篇职责
回答“赋值、算术、比较、逻辑、位运算、集合/类型关系、条件求值、表达式对象、访问/调用和专题运算符入口在 TSL 里怎样写”。
回答“赋值、算术、比较、逻辑、位运算、集合/类型关系、条件求值、表达式对象、访问/调用、点前缀运算符和专题运算符入口在 TSL 里怎样写”。
## 智能体表达式/运算符判断流程
@ -18,16 +18,17 @@
2. 普通变量赋值只能用 `:=`,不要把 `=` 当赋值写法;`const name = value;` 是常量初始化规则,回看 [04_variables_and_constants.md](04_variables_and_constants.md)。
3. 在普通表达式里,比较才用 `=`,并且把比较表达式放在 `writeLn(...)`、条件或其他需要布尔值的位置。
4. 函数签名里的默认参数 `name = value` 不是比较表达式;默认参数规则回 [05_functions_and_calls.md](05_functions_and_calls.md)。
5. 普通算术优先使用 `+`、`-`、`*`、`/`、`%`;整数除法和取模可用 `div`、`mod`;幂运算用 `^`;一元倒数用 `!x`
6. 逻辑表达式优先使用 `and`、`or`、`not``&&`、`||` 也已可用,但不要把 `!` 写成逻辑非。
7. 已有变量做原地更新时,才使用 `+=`、`-=`、`*=`、`/=`、`%=`、`^=`、`.&=`、`.|=`、`.^=`、`a++;`、`a--;`、`++a;`、`--a;`。
8. 条件求值优先用 `flag ? true_value : false_value`;需要 Pascal 风格时可用 `if condition then true_value else false_value` 的形态,但必须带 `else`
9. 需要延迟求值或动态表达式对象时,才使用 `@expr``&"..."`,并用本页明确的 `eval(...)` 形态求值。
10. 空安全访问只照本页文档明确形态写:`a?.member`、`a?.[index]`、以及 `c?.a?.[1]`。不要外推成任意深度、任意组合都可写。
11. 需要连续比较时,标量用 `:<` / `:>` 这组链式比较;数组逐元素比较用 `::<` / `::>` 这组矩阵链式比较。
12. 命中集合、矩阵、对象重载、函数值调用、网格调用、运行时后缀或 TS-SQL 时,按“专题运算符入口表”跳到对应页面。
13. `{$ifdef ...}` 只作为能力探测;编译选项边界回 [16_lexical_structure_and_compile_options.md](16_lexical_structure_and_compile_options.md)。
14. 任务需要的运算符没有文档事实时,不要生成猜测写法;只能切到对应专题页、项目自身文档或项目专属规则,仍无结论时记录文档缺口。
5. 普通算术优先使用 `+`、`-`、`*`、`/`、`%`;左除用 `\`;整数除法和取模可用 `div`、`mod`;幂运算用 `^`;对数用 `~`;一元倒数用 `!x`
6. 逻辑表达式优先使用 `and`、`or`、`not``&&`、`||`、`.&&`、`.||`、`.!!` 也已可用,但默认不作为主写法;不要把 `!` 写成逻辑非。
7. 位运算使用点前缀或移位关键字:`.&`、`.|`、`.!`、`.^`、`shl`、`shr`、`rol`、`ror`;普通 `&`、`|`、`~` 不按位运算理解。
8. 已有变量做原地更新时,才使用 `+=`、`-=`、`*=`、`/=`、`\=`、`%=`、`^=`、`~=`、`div=`、`.&=`、`.|=`、`.^=`、`.&&=`、`.||=`、`a++;`、`a--;`、`++a;`、`--a;`。
9. 条件求值优先用 `flag ? true_value : false_value`;需要保留条件自身真值时可用 `value ?: fallback_value`;需要 Pascal 风格时可用 `if condition then true_value else false_value` 的形态,但必须带 `else`
10. 需要延迟求值或动态表达式对象时,才使用 `@expr``&"..."`,并用本页明确的 `eval(...)` 形态求值。
11. 空安全访问只照本页文档明确形态写:`a?.member`、`a?.[index]`、以及 `c?.a?.[1]`。不要外推成任意深度、任意组合都可写。
12. 需要连续比较时,标量用 `:<` / `:>` 这组链式比较;数组逐元素比较用 `::<` / `::>` 这组矩阵链式比较。
13. 命中集合、矩阵、过滤、对象重载、函数值调用、网格调用、运行时后缀或 TS-SQL 时,按“专题运算符入口表”跳到对应页面。
14. `{$ifdef ...}` 只作为能力探测;编译选项边界回 [16_lexical_structure_and_compile_options.md](16_lexical_structure_and_compile_options.md)。
15. 任务需要的运算符没有文档事实时,不要生成猜测写法;只能切到对应专题页、项目自身文档或项目专属规则,仍无结论时记录文档缺口。
## 核心规则
@ -39,20 +40,24 @@
| 类别 | 运算符 / 形态 | 生成规则 |
| --- | --- | --- |
| 普通赋值 | `:=` | 变量赋值默认只用 `:=`。 |
| 多变量赋值 | `[a, b] := array(...)`、`[a, ] := array(...)` | 需要从数组按位置拆出多个值时使用;只有一个接收变量时保留末尾逗号。 |
| 常量初始化 | `const name = value;` | 这是常量声明规则,不按普通赋值处理。 |
| 函数默认参数 | `name = value` | 这是函数签名规则,不按比较表达式处理。 |
| 复合赋值 | `+=`、`-=`、`*=`、`/=`、`%=`、`^=`、`.&=`、`.&#124;=`、`.^=` | 已有变量需要原地更新时使用。 |
| 算术复合赋值 | `+=`、`-=`、`*=`、`/=`、`\=`、`%=`、`^=`、`~=`、`div=` | 已有变量需要原地更新时使用;`div=` 是整除复合赋值。 |
| 点前缀复合赋值 | `.&=`、`.&#124;=`、`.^=`、`.&&=`、`.&#124;&#124;=` | 位运算或点前缀逻辑需要原地更新时使用。 |
| 自增 / 自减 | `a++`、`a--`、`++a`、`--a` | 普通数字变量可直接用;对象重载语义回 [24_object_overloads_and_iteration.md](24_object_overloads_and_iteration.md)。 |
| 算术 | `+`、`-`、`*`、`/`、`%`、`div`、`mod`、`^` | 普通数值计算使用;`^` 是幂运算。 |
| 算术 | `+`、`-`、`*`、`/`、`\`、`%`、`div`、`mod`、`^`、`~` | 普通数值计算使用;`\` 是左除,`^` 是幂运算,`~` 是对数运算。 |
| 一元正负号 | `+x`、`-x` | 可直接用于数值表达式。 |
| 一元倒数 | `!x` | 整型、实型输入返回实型倒数;矩阵逆/广义逆回 [22_matrix_deep_dive.md](22_matrix_deep_dive.md)。 |
| 字符串连接 | `+`、`$` | 字符串拼接两种写法都已写入文档;默认优先用 `+`。 |
| 比较 | `=`、`<>`、`<`、`>`、`<=`、`>=` | `=` 只作比较,不作普通赋值。 |
| 逻辑 | `and`、`or`、`not`、`&&`、&#124;&#124; | 默认优先写 `and` / `or` / `not`;不要用 `!` 表示逻辑非。 |
| 位运算 | `.&`、`.&#124;`、`.^` | 生成代码时写成无空格形态:`.&`、`.&#124;`、`.^`。 |
| 点前缀比较 | `.=`、`.<>`、`.<`、`.>`、`.<=`、`.>=` | 标量比较可用;数组/矩阵样数据上的逐元素语义回 [12_matrix_and_collections.md](12_matrix_and_collections.md)。 |
| 逻辑 | `and`、`or`、`not`、`&&`、`&#124;&#124;`、`.&&`、`.&#124;&#124;`、`.!!` | 默认优先写 `and` / `or` / `not`;不要用 `!` 表示逻辑非。 |
| 位运算 | `.&`、`.&#124;`、`.!`、`.^`、`shl`、`shr`、`rol`、`ror` | 生成代码时写成点前缀或关键字形态;普通 `&`、`&#124;`、`~` 不作为位运算写法。 |
| 成员 / 下标 / 调用 | `obj.member`、`value[index]`、`Func(args)` | 普通访问和调用可直接使用;类、对象、函数细节回对应专题。 |
| 空安全访问 | `a?.member`、`a?.[index]`、`c?.a?.[1]` | 只按已写入文档形态生成。 |
| 条件求值 | `flag ? true_value : false_value` | 普通条件表达式默认写法。 |
| 省略真值的条件求值 | `value ?: fallback_value` | 条件为真时返回条件自身的值;条件为假时返回后备值。 |
| Pascal 风格条件表达式 | `if condition then true_value else false_value` | 必须带 `else`。 |
| 表达式对象 | `@expr`、`&"..."` | 需要延迟求值或动态表达式对象时使用,并用 `eval(...)` 求值。 |
| 逗号表达式 | `(exp1, exp2, ..., expN)` | 从左到右求值,返回最后一个表达式结果。 |
@ -69,9 +74,11 @@
| 调用点 `in` / `out`、变参 `...` | [05_functions_and_calls.md](05_functions_and_calls.md) | 这是参数传递 / 变参规则,不按普通表达式运算符处理。 |
| `#Func() with array(...)` | [10_runtime_context_and_with.md](10_runtime_context_and_with.md) | 运行时环境参数调用只按运行时上下文页生成。 |
| `#Func(args)`、`timeout N`、`dupvalue(...)` | [10_runtime_context_and_with.md](10_runtime_context_and_with.md) | 网格调用和运行时服务后缀只按运行时上下文页生成。 |
| `union2`、`intersect`、`minus`、`outersect` | [12_matrix_and_collections.md](12_matrix_and_collections.md) | 行集合并、交、差、对称差只按数组/集合页生成。 |
| `union`&#124;、`:&#124;` | [23_fmarray.md](23_fmarray.md) | `FMArray` 行拼接和矩阵并右方(按列拼接)只按 `FMArray` 页生成。 |
| `->`、`!matrix` | [22_matrix_deep_dive.md](22_matrix_deep_dive.md) | 数列数组初始化、矩阵逆/广义逆只按矩阵深水页生成。 |
| `union2`、`intersect`、`minus`、`outersect`、`union2=`、`intersect=`、`minus=`、`outersect=` | [12_matrix_and_collections.md](12_matrix_and_collections.md) | 行集合并、交、差、对称差及其复合赋值只按数组/集合页生成。 |
| `filterIn(...)`、`filterNotIn(...)` | [13_resultset_and_filters.md](13_resultset_and_filters.md) | 结果集过滤只按过滤页生成,不当作去重型集合运算。 |
| `:*`、`:/`、`:\`、`:^`、`union`、&#124;、`:&#124;`、`&#124;=`、`:&#124;=`、`&=`、`:*=`、`:/=`、`:\=`、`:^=` | [22_matrix_deep_dive.md](22_matrix_deep_dive.md)、[23_fmarray.md](23_fmarray.md) | 矩阵乘除、左右拼接、下方拼接和矩阵复合赋值只按矩阵专题页生成。 |
| `->`、`!matrix`、`.?`、`.?:` | [22_matrix_deep_dive.md](22_matrix_deep_dive.md) | 数列数组初始化、矩阵逆/广义逆、矩阵条件求值只按矩阵深水页生成。 |
| `::`、`::=`、`:.`、`:.=` | [22_matrix_deep_dive.md](22_matrix_deep_dive.md)、[24_object_overloads_and_iteration.md](24_object_overloads_and_iteration.md) | 矩阵遍历/深度遍历和对象遍历重载只按专题页生成,不在普通表达式里自行套用。 |
| 反引号转置 `` `value `` | [23_fmarray.md](23_fmarray.md) | `FMArray` 转置只按 `FMArray` 页生成。 |
| `operator +`、`operator <`、`operator[]`、`operator[0]`、`operator[1]`、`operator for`、`operator mrows/mcols/msize`、`operator++`、`operator +=` | [24_object_overloads_and_iteration.md](24_object_overloads_and_iteration.md) | 对象运算符重载只按对象重载页生成。 |
| `select` / `sselect` / `vselect` / `mselect`、`where`、`group by`、`order by`、`join` | [14_ts_sql.md](14_ts_sql.md) | TS-SQL 是查询语法,不按普通表达式拼接。 |
@ -82,25 +89,28 @@
- 普通变量赋值使用 `:=`;常量初始化不按普通赋值判断,见 [04_variables_and_constants.md](04_variables_and_constants.md)。
- `=` 在普通表达式里用于比较,不用于赋值。
- `const name = value;` 和函数签名默认参数 `name = value` 不按本页普通表达式比较判断。
- 普通算术使用 `+`、`-`、`*`、`/`、`%`、`div`、`mod`、`^`。
- 普通算术使用 `+`、`-`、`*`、`/`、`\`、`%`、`div`、`mod`、`^`、`~`。
- 需要数值倒数时用 `!x`;整型和实型输入都会得到实型结果。
- 普通逻辑优先使用 `and`、`or`、`not``&&`、`||` 已写入文档但不作为默认主写法。
- 普通条件求值默认用 `flag ? true_value : false_value`
- 需要把条件自身作为真值返回时,使用 `value ?: fallback_value`
- 需要 Pascal 风格表达式时,才用 `if condition then true_value else false_value`,且必须带 `else`
- 字符串拼接默认用 `+`;需要明确字符串连接时也可用 `$`
- 字符串匹配用 `like` 时按正则理解,不按 SQL `%` 通配理解。
按需生成规则:
- 已有变量需要原地更新时,才用 `+=`、`-=`、`*=`、`/=`、`%=`、`^=`、`.&=`、`.|=`、`.^=`、`a++;`、`a--;`、`++a;`、`--a;`。
- 已有变量需要原地更新时,才用 `+=`、`-=`、`*=`、`/=`、`\=`、`%=`、`^=`、`~=`、`div=`、`.&=`、`.|=`、`.^=`、`.&&=`、`.||=`、`a++;`、`a--;`、`++a;`、`--a;`。
- 需要矩阵逆/广义逆时才使用 `!A`,并回 [22_matrix_deep_dive.md](22_matrix_deep_dive.md) 确认矩阵生成规则。
- 位运算需要明确写成点前缀形态:`.&`、`.|`、`.^`;普通 `&` 不作为位与写法使用。
- 位运算需要明确写成点前缀或关键字形态:`.&`、`.|`、`.!`、`.^`、`shl`、`shr`、`rol`、`ror`;普通 `&` 不作为位与写法使用。
- 点前缀比较 `.=`、`.<>`、`.<`、`.>`、`.<=`、`.>=` 命中数组/矩阵样数据时,先回 [12_matrix_and_collections.md](12_matrix_and_collections.md) 判断逐元素语义。
- 需要延迟求值或动态表达式对象时,才用 `@expr``&"..."`,并用 `eval(...)` 求值。
- 需要在一个表达式内按顺序执行多个子表达式时,才用逗号表达式 `(exp1, exp2, ..., expN)`
- 空安全访问只按 `a?.member`、`a?.[index]` 和本页示例里的 `c?.a?.[1]` 生成,不外推任意深链。
- 否定形式只照 `not in`、`not like`、`not sqlin`、`not is` 这几种文档明确写法生成。
- 连续标量比较才用 `:>`、`:<`、`:<>`、`:==`、`:>=`、`:<=`。
- 数组逐元素链式比较才用 `::>`、`::<`、`::<>`、`::==`、`::>=`、`::<=`。
- 混合两类以上运算符时,优先用括号明确分组,不依赖跨语言记忆里的优先级。
边界规则:
@ -136,6 +146,42 @@ writeLn(value);
10
```
省略真值的条件求值:
代码块身份:可直接照写示例
```tsl
writeLn(2 ?: 9);
writeLn(0 ?: 9);
```
代码块身份:输出片段
```text
2
9
```
多变量赋值:
代码块身份:可直接照写示例
```tsl
[a, b] := array(1, 2, 3);
writeLn(a);
writeLn(b);
[first_value, ] := array(4, 5);
writeLn(first_value);
```
代码块身份:输出片段
```text
1
2
4
```
运算赋值:
代码块身份:可直接照写示例
@ -161,10 +207,12 @@ writeLn(1 + 2);
writeLn(5 - 2);
writeLn(3 * 4);
writeLn(8 / 2);
writeLn(3 \ 2);
writeLn(9 % 4);
writeLn(9 div 4);
writeLn(9 mod 4);
writeLn(2 ^ 3);
writeLn(8 ~ 2);
writeLn(-3 + 5);
writeLn(+3);
```
@ -176,10 +224,12 @@ writeLn(+3);
3
12
4
0.666666666666667
1
2
1
8
3
2
3
```
@ -208,6 +258,30 @@ writeLn(2 <> 3);
1
```
点前缀比较:
代码块身份:可直接照写示例
```tsl
writeLn(2 .= 2);
writeLn(2 .<> 3);
writeLn(1 .< 2);
writeLn(2 .> 1);
writeLn(2 .<= 2);
writeLn(2 .>= 2);
```
代码块身份:输出片段
```text
1
1
1
1
1
1
```
一元倒数:
代码块身份:可直接照写示例
@ -245,8 +319,11 @@ writeLn(dataType(rb));
writeLn((1 < 2) and (2 < 3));
writeLn((1 > 2) or (2 < 3));
writeLn(not (1 > 2));
writeLn(.!! 0);
writeLn((1 < 2) && (2 < 3));
writeLn((1 > 2) || (2 < 3));
writeLn(1 .&& 0);
writeLn(0 .|| 2);
```
代码块身份:输出片段
@ -257,6 +334,9 @@ writeLn((1 > 2) || (2 < 3));
1
1
1
1
0
1
```
位运算:
@ -267,6 +347,11 @@ writeLn((1 > 2) || (2 < 3));
writeLn(6 .& 3);
writeLn(4 .| 1);
writeLn(6 .^ 3);
writeLn(.! 1);
writeLn(1 shl 2);
writeLn(8 shr 1);
writeLn(1 rol 1);
writeLn(2 ror 1);
```
代码块身份:输出片段
@ -275,6 +360,11 @@ writeLn(6 .^ 3);
2
5
5
-2
4
4
2
1
```
基础算术复合赋值:
@ -291,6 +381,15 @@ a /= 7;
writeLn(a);
a %= 5;
writeLn(a);
b := 3;
b \= 2;
writeLn(b);
c := 8;
c ~= 2;
writeLn(c);
d := 7;
d div= 3;
writeLn(d);
```
代码块身份:输出片段
@ -300,6 +399,9 @@ writeLn(a);
28
4
4
0.666666666666667
3
2
```
幂运算和位运算也可以使用复合赋值:
@ -319,6 +421,12 @@ writeLn(c);
d := 6;
d .^= 3;
writeLn(d);
e := 0;
e .||= 2;
writeLn(e);
f := 1;
f .&&= 0;
writeLn(f);
```
代码块身份:输出片段
@ -328,6 +436,8 @@ writeLn(d);
2
5
5
1
0
```
字符串同样支持 `+=`

View File

@ -17,7 +17,7 @@
1. 先判断任务需要条件分支、循环、`case`、异常处理还是调试跳转。
2. `if` / `for` / `while` / `repeat` 优先照本页文档骨架写,不要套用其他 Pascal 方言。
3. 生成带 `else` 的条件分支时,默认用 `begin ... end` 包住 `then``else` 分支,让分支内部语句正常以分号结尾;控制流块的 `end` 默认不加分号,也不要在 `else` 前提前加分号。
4. `case` 只按语句形态生成;不要把 `case` 放到赋值右侧生成表达式形态
4. `case` 可写成语句形态,也可写成赋值右侧的表达式形态;表达式形态的分支只能放单条表达式/单条语句,不写 `begin ... end` 语句段
5. 没有文档事实时不要发明控制流写法。
## 核心规则
@ -27,7 +27,8 @@
- `for` 支持 `to`、`downto`、可选 `step`,以及 `for i, v in array` 遍历。
- `while``repeat ... until` 都可直接使用;`repeat` 至少会先执行一轮再判断结束条件。
- `break` 会跳出当前最近一层循环,`continue` 会跳过当前轮剩余语句。
- `case ... of ... else ... end` 只作为语句形态生成;`end` 后默认不加分号。
- `case ... of ... else ... end` 可作为语句形态生成;语句形态的 `end` 后默认不加分号。
- `value := case ... of ... else ... end;` 可作为表达式形态生成;表达式形态赋值语句本身要用分号结尾。
- `case` 分支标签支持逗号并列和 `to` 区间。
- `try ... except ... end` 可以捕获 `raise` 产生的错误,并继续执行后续语句。
- `exceptObject.errInfo``except` 块中可读,能拿到当前错误信息。
@ -274,6 +275,39 @@ end
mid
```
`case` 表达式形态:
代码块身份:可直接照写示例
```tsl
a := 3;
label_value := case a of
1, 2:
"small";
3, 4:
"mid";
else
"other";
end;
writeLn(label_value);
```
输出说明:
- 输出 `mid`
代码块身份:输出片段
```text
mid
```
说明:
- 表达式形态可以放在赋值右侧。
- 表达式形态的每个分支只写单条表达式/单条语句,不写 `begin ... end` 语句段。
- 赋值语句整体以 `end;` 收尾。
### `try ... except`
代码块身份:可直接照写示例

View File

@ -6,15 +6,15 @@
是否含不可照写反例:是
遇到不确定时:先按本页候选页继续判断;[05_functions_and_calls.md](05_functions_and_calls.md)、[06_expressions_and_operators.md](06_expressions_and_operators.md)、[14_ts_sql.md](14_ts_sql.md)、[15_debug_and_profiler.md](15_debug_and_profiler.md)、[19_namespace_libpath_and_unit_runtime.md](19_namespace_libpath_and_unit_runtime.md)、[21_builtin_runtime_objects.md](21_builtin_runtime_objects.md)、[../reference/catalog/datawarehouse.md](../reference/catalog/datawarehouse.md);仍不命中时回到语法路由中心 [index.md](index.md);如果问题已经超出语法层,回到 TSL 总入口 [../index.md](../index.md)
这一篇只处理运行时环境参数、`with` 后缀、`#` 网格调用、`timeout` 后缀、`dupvalue(...)` 和全局缓存,不处理任何金融业务语义。
这一篇只处理运行时环境参数、块环境 `with` 语句、`with` 后缀、`#` 网格调用、`timeout` 后缀、`dupvalue(...)` 和全局缓存,不处理任何金融业务语义。
## 本篇职责
回答“`setSysParam` / `getSysParam` 怎样用、`sysParams[...]` 是什么、`#Func() with array(...)` 这种后缀环境调用怎样写,网格调用怎样取回结果,以及全局缓存最小读写规则是什么”。
回答“`setSysParam` / `getSysParam` 怎样用、`sysParams[...]` 是什么、块环境 `with *, values do` / `with **, values do` 怎样写、`#Func() with array(...)` 这种后缀环境调用怎样写,网格调用怎样取回结果,以及全局缓存最小读写规则是什么”。
## 智能体运行时上下文判断流程
1. 先判断要操作系统参数、运行时上下文对象、`with` 后缀调用、`#` 网格调用、`timeout` 后缀,还是全局缓存函数。
1. 先判断要操作系统参数、运行时上下文对象、块环境 `with` 语句、`with` 后缀调用、`#` 网格调用、`timeout` 后缀,还是全局缓存函数。
2. 系统参数优先用本页明确的 `setSysParam` / `getSysParam` / `sysParams[...]` 形态。
3. `#Func() with array(...)` 只作为运行时环境调用写法,不要套到普通本地函数。
4. 网格调用返回的不是最终值;需要最终结果时继续写 `dupvalue(...)`
@ -29,7 +29,10 @@
- TSL 有一组运行时系统参数;本页只写通用语法形态。
- `setSysParam(key, value)``getSysParam(key)` 可以直接用字符串键。
- `sysParams[key]` 可以直接读写这些运行时参数。
- 本页明确的 `with` 形式,是写在函数文件调用后面:`#Func() with array(...)`。
- 块环境语句可写成 `with *, sys_param_values do begin ... end``with **, sys_param_values do begin ... end`
- `with *` 会把提供的系统参数合并进当前运行时上下文;不要依赖它在块结束后自动恢复外层值。
- `with **` 会用提供的系统参数建立隔离块环境;块结束后恢复外层系统参数。
- 后缀 `with` 形式写在函数文件调用后面:`#Func() with array(...)`。
- `with array(...)` 只在该次调用里临时覆盖对应键,调用结束后会恢复外部原值。
- 如果外部原值本来不存在,`with array(...)` 调用结束后,对应键会恢复成 `nil`
- 不要把上面的后缀 `with` 直接泛化成“任何本地函数调用后面都能接 `with array(...)`”;本地函数后缀 `with` 属于反例。
@ -85,6 +88,55 @@ writeLn(getSysParam("a"));
- 依次输出 `321`、`QQ`、`321`
- 说明 `sysParams[...]``getSysParam(...)` / `setSysParam(...)` 指向的是同一组运行时环境参数
### 块环境 `with *`
代码块身份:可直接照写示例
```tsl
setSysParam("a", 1);
sys_param_values := array("a": 2, "b": 3);
with *, sys_param_values do
begin
writeLn(getSysParam("a"));
writeLn(getSysParam("b"));
end
writeLn(getSysParam("a"));
writeLn(getSysParam("b"));
```
结果说明:
- 块内输出 `2`、`3`
- 块后输出 `2`、`3`
- 说明 `with *` 会把传入键合并进当前系统参数上下文;不要把它当成自动恢复外层值的隔离块
### 块环境 `with **`
代码块身份:可直接照写示例
```tsl
setSysParam("a", 1);
setSysParam("b", 9);
sys_param_values := array("b": 4);
with **, sys_param_values do
begin
writeLn(getSysParam("a") = nil);
writeLn(getSysParam("b"));
end
writeLn(getSysParam("a"));
writeLn(getSysParam("b"));
```
结果说明:
- 块内输出 `1`、`4`
- 块后输出 `1`、`9`
- 说明 `with **` 不继承未传入的外层系统参数,并且块结束后恢复外层系统参数
沿用同一个 `TestDo.tsf`,看 `with array(...)` 的覆盖边界:
代码块身份:配置片段 / 概念骨架
@ -259,6 +311,8 @@ writeLn(q[0][0], ',', q[0][1], ';', q[1][0], ',', q[1][1], ';', q[2][0], ',', q[
- 网格超时触发错误时的完整边界
- `getGlobalCacheInfo`、`listGlobalCache`、`listGlobalCacheRemoved`
- 初始化 TSL、监控线程、回收策略与兼容旧系统方案
- `with [S => ..., T => ...] do` 块语句
- `{$include ...}` 包含文件指令
这些名称只作为边界提示,不作为本页可生成模板。
@ -292,6 +346,7 @@ end;
- 把系统参数页直接写成金融函数页。
- 把 `#Func() with array(...)` 误判成也能直接套在本地函数 `Demo()` 后面。
- 把 `with *` 误判成会自动恢复外层系统参数。
- 以为 `with array(...)` 改的是全局永久值,不会恢复外层原环境。
- 把网格句柄直接当最终值用,而不做 `dupvalue(...)`
- 以为从全局缓存取出的值,本地写入后仍然保持缓存身份。

View File

@ -28,9 +28,34 @@
- 条件编译只编译命中的分支;未命中的分支不参与脚本编译。
- `{$explicit+}` 开启后,后续变量必须先用 `var` 声明;`{$explicit-}` 可以在同一源文件里重新关闭这个要求。
- `{$varByRef-}``{$varByRef+}` 会切换“未修饰形参”的默认传递方式,细节见 [05_functions_and_calls.md](05_functions_and_calls.md)。
- 保留字/关键字大小写无关,不要拿来当普通变量、函数或类名;例如 `params` 是函数参数访问关键字,不适合作为普通变量名。
- `{$i}` / `{$include}` 不作为本页可生成的默认能力。
- `{$dependency ...}` 这类编辑器辅助编译选项不作为本页正文事实。
## 保留字/关键字速查
TSL 关键字大小写无关;本表统一按文档推荐写法展示。生成代码时不要把这些名称用作普通标识符。
<!-- prettier-ignore-start -->
| 分类 | 关键字 / 保留名 | 生成规则 |
| --- | --- | --- |
| 程序与函数结构 | `program`、`function`、`procedure`、`begin`、`end`、`return`、`exit` | 默认写函数时使用 `function``procedure` 只在用户明确要求时使用。 |
| 控制流 | `if`、`then`、`else`、`case`、`of`、`for`、`to`、`downto`、`step`、`while`、`do`、`repeat`、`until`、`break`、`continue`、`goto`、`label` | 具体语句形态回 [07_control_flow.md](07_control_flow.md)。 |
| 异常控制 | `try`、`except`、`finally`、`raise`、`exceptObject` | 异常语法回 [07_control_flow.md](07_control_flow.md)。 |
| 值与容器 | `nil`、`true`、`false`、`nan`、`inf`、`array` | 字面量与数组基础回 [03_values_and_literals.md](03_values_and_literals.md) 和 [12_matrix_and_collections.md](12_matrix_and_collections.md)。 |
| 运算关键字 | `and`、`or`、`not`、`in`、`sqlin`、`like`、`is`、`div`、`mod`、`shl`、`shr`、`rol`、`ror` | 运算符规则回 [06_expressions_and_operators.md](06_expressions_and_operators.md)。 |
| 参数访问 | `params`、`paramCount`、`realParamCount`、`var`、`out`、`const` | 普通参数优先写具名形参;`params` / `paramCount` / `realParamCount` 只用于变参或参数个数判断。 |
| 运行时上下文 | `sysParams`、`system`、`debugReturn`、`debugRunEnv`、`debugRunEnvDo`、`echo`、`global`、`static`、`thisFunction`、`_myMem_`、`_maxMem_`、`__line__`、`__stack_frame` | 运行时系统参数回 [10_runtime_context_and_with.md](10_runtime_context_and_with.md);调试相关回 [15_debug_and_profiler.md](15_debug_and_profiler.md)。 |
| LIKE 精度 | `likeEps`、`likeEpsRate` | 只在需要调整 `like` 数值近似判断阈值时使用。 |
| 类与对象 | `type`、`class`、`new`、`findClass`、`findFunction`、`fackClass`、`property`、`self`、`virtual`、`override`、`overload`、`protected`、`public`、`private`、`published`、`static` | 类声明、对象创建和成员规则回 [08_objects_and_classes.md](08_objects_and_classes.md)。 |
| 外部调用约定 | `external`、`cdecl`、`pascal`、`stdcall`、`safecall`、`fastcall`、`register` | 外部调用细节回 [18_external_calls_and_threads.md](18_external_calls_and_threads.md)。 |
| 客户端远程调用与权限 | `rdo`、`rdo2`、`sudo`、`setUid` | 平台/客户端远程调用和权限语义不作为普通本地语法模板。 |
| TS-SQL 查询 | `select`、`vselect`、`sselect`、`mselect`、`distinct`、`selectOpt`、`dRange`、`as`、`from`、`marketTable`、`infoTable`、`tradeTable`、`sqlTable`、`hugeSqlTable`、`keepNull`、`dateKey`、`of`、`order`、`by`、`where`、`desc`、`asc`、`group`、`having` | 查询语法回 [14_ts_sql.md](14_ts_sql.md)。 |
| TS-SQL 聚合与上下文 | `checksumOf`、`countOf`、`sumOf`、`maxOf`、`stdevOf`、`varOf`、`totalVarOf`、`normOf`、`medianOf`、`aveDevOf`、`geoMeanOf`、`skewOf`、`kurtosisOf`、`skew2Of`、`kurtosis2Of`、`largeOf`、`percentileOf`、`quartileOf`、`trimMeanOf`、`avgOf`、`minOf`、`aggOf`、`stdevpOf`、`varpOf`、`modeOf`、`devSqOf`、`harMeanOf`、`checksum_aggOf`、`smallOf`、`percentRankOf`、`rankOf`、`frequencyOf`、`productOf`、`refOf`、`refsOf`、`aggValue`、`thisGroup`、`thisRow`、`thisRowIndex`、`thisOrder` | 这些名称只在 TS-SQL 语境中生成。 |
| TS-SQL 写入 | `insert`、`insertFields`、`values`、`update`、`set`、`delete`、`deleteOpt`、`fetchFirst`、`fetchNext` | 写回/变更型查询只按 TS-SQL 专题页生成。 |
| 系统保留未使用 | `exports`、`dispInterface`、`library`、`asm`、`record`、`resourceString`、`threadVar`、`constructor`、`destructor`、`inline`、`packed`、`abstract`、`inherited` | 这些名称被系统保留,不作为普通标识符使用,也不作为可写语法模板。 |
<!-- prettier-ignore-end -->
## 可直接照写示例
### 标识符、注释与条件编译

View File

@ -24,13 +24,19 @@
- `TStringList` 可以直接用 `new TStringList()` 创建。
- `TStringList` 支持数字下标、字符串键下标、`Count` 和 `Add(...)`
- `THashedStringList` 可以直接创建,最小用法与 `TStringList` 接近,适合按名称快速取值。
- 流对象应先按 `TStream` 家族理解;普通脚本里的最小可靠入口是 `TMemoryStream` 这种具体类型。
- 直接 `new TStream()` 会失败,错误信息包含 `function:TStream compile error or not found`
- `TMemoryStream` 支持 `Write(...)`、`Read(...)`、`Position`、`Size`。
- `TFileStream` 可以带目录别名、文件名和打开模式创建,并支持 `TStream` 的读写位置模型。
- `TCipher` 不是“无参即可创建”的对象;`new TCipher()` 会失败。
- `TCipher` 的最小写法是 `new TCipher(2)`,然后设置 `Password` 再做 `Encrypt(...)` / `Decrypt(...)`
- `TRsa` 可以直接创建;先 `GenerateKey(...)`,再读取 `PublicKey` / `PrivateKey` 或执行公私钥加解密。
- `TIniFile` 适合读写磁盘 INI 文件;`TMemIniFile` 适合内存 INI 数据。
- `MailMsg``MessagePart` 可以直接创建并设置消息字段,但发送邮件流程属于 SMTP 对象/外部服务边界。
- `TWebRequest``TWebResponse` 在普通脚本里不作为可直接 `new` 的对象。
- 因此Web 请求 / 响应对象不要直接写进普通脚本模板;它们应视为特定运行上下文对象。
- 本页不承担对象完整方法表;只收能让 agent 稳定生成代码的最小入口。
- 本页失败创建示例只用于边界判断,不作为业务代码模板复制。
## 可直接照写示例
@ -54,15 +60,23 @@ writeLn(obj.Count);
- 依次输出 `B=bbb`、`bbb`、`3`、`4`
- 说明既可以按数字下标取整行,也可以按键名取 `Name=Value` 里的值
代码块身份:输出片段
### `THashedStringList`
```text
B=bbb
bbb
3
4
代码块身份:可直接照写示例
```tsl
obj := new THashedStringList();
obj.Add("A=aaa");
obj.Add("B=bbb");
writeLn(obj.Count);
writeLn(obj["B"]);
```
结果说明:
- 依次输出 `2`、`bbb`
- 说明 `THashedStringList` 可按 `Name=Value` 的名称键读取值
### `TStream` 家族的最小可靠入口:`TMemoryStream`
代码块身份:可直接照写示例
@ -83,6 +97,27 @@ writeLn(mem.Size);
- 依次输出 `ABC`、`3`
- 说明普通脚本里应优先使用 `TMemoryStream` 这类具体流对象。
`TFileStream` 可直接打开文件并沿用 `TStream``Write(...)` / `Read(...)` / `Position` / `Size` 模型:
代码块身份:可直接照写示例
```tsl
file_name := "object_probe.txt";
stream := new TFileStream("", file_name, 65535);
buffer := "ABC";
stream.Write(buffer, 3);
writeLn(stream.Size);
stream.Position := 0;
outbuf := "xxx";
stream.Read(outbuf, 3);
writeLn(outbuf);
```
结果说明:
- 依次输出 `3`、`ABC`
- `TFileStream("", file_name, 65535)` 可作为最小读写文件流骨架
`TStream` 创建反例:
代码块身份:反例 / 不可照写
@ -130,6 +165,88 @@ writeLn(cipher.Decrypt(enc));
- 依次输出 `1`、`abc`
- 说明 `TCipher` 必须按“带模式参数创建”来写,随后可稳定走 `Password -> Encrypt -> Decrypt`
### `TRsa`
代码块身份:可直接照写示例
```tsl
rsa := new TRsa();
rsa.GenerateKey(1024);
plain := "abc";
enc := rsa.PubEncrypt(plain);
writeLn(rsa.PriDecrypt(enc));
enc2 := rsa.PriEncrypt(plain);
writeLn(rsa.PubDecrypt(enc2));
writeLn(length(rsa.PublicKey) > 0);
writeLn(length(rsa.PrivateKey) > 0);
```
结果说明:
- 依次输出 `abc`、`abc`、`1`、`1`
- 说明 `TRsa` 先生成密钥,再用公钥加密 / 私钥解密,或私钥加密 / 公钥解密
### `TIniFile``TMemIniFile`
磁盘 INI 文件:
代码块身份:可直接照写示例
```tsl
ini := new TIniFile("", "object_probe.ini");
ini.WriteString("S", "K", "V");
writeLn(ini.ReadString("S", "K", ""));
ini.WriteInteger("S", "N", 123);
writeLn(ini.ReadInteger("S", "N", 0));
```
结果说明:
- 依次输出 `V`、`123`
- 说明 `TIniFile` 适合直接读写磁盘 INI 文件
内存 INI 数据:
代码块身份:可直接照写示例
```tsl
ini := new TMemIniFile();
ini.WriteString("S", "K", "V");
writeLn(ini.ReadString("S", "K", ""));
```
结果说明:
- 输出 `V`
- 说明 `TMemIniFile` 可不依赖磁盘文件,直接读写内存 INI 数据
### `MailMsg``MessagePart`
代码块身份:可直接照写示例
```tsl
msg := new MailMsg();
msg.Subject := "Hello";
msg.Body := "BodyText";
msg.Sender := "sender@example.com";
msg.Recipients := "to@example.com";
writeLn(msg.Subject);
writeLn(msg.Body);
writeLn(length(msg.AsString) > 0);
part := new MessagePart();
part.ContentType := "text/plain";
part.Body := "PartBody";
writeLn(part.ContentType);
writeLn(part.Body);
```
结果说明:
- 依次输出 `Hello`、`BodyText`、`1`、`text/plain`、`PartBody`
- 说明 `MailMsg` / `MessagePart` 可作为消息数据对象使用
- 发送邮件应回到 SMTP 对象和外部服务配置,不在本页生成连接/认证/发送模板
### `TWebRequest` / `TWebResponse` 的普通脚本边界
代码块身份:反例 / 不可照写
@ -145,24 +262,23 @@ resp := new TWebResponse();
- `new TWebResponse()` 会报 `function:TWebResponse compile error or not found`
- 普通脚本里Web 请求 / 响应对象不能直接按普通 `new ...()` 脚本对象来写。
## 本页不生成的对象
## 本页不生成的范围
- `TFileStream`
- `TIniFile`
- `TMemIniFile`
- `THashedStringList`
- `TRSA`
- `FTP` / `SMTP` / `POP3`
- `MailMsg` / `MessagePart`
- `TCookie` / `TCookieCollection`
- `TSessionMan` / `TSession`
- `FTP` / `SMTP` / `POP3` 的连接、认证、上传下载、发送邮件和收取邮件流程。
- `TWebRequest` / `TWebResponse` 的 Web 请求响应流程。
- `TCookie` / `TCookieCollection`
- `THandleStream`
- `TRegistryIniFile`
- `TSessionMan` / `TSession`
这些对象不作为本页可生成事实;不要因为未写入文档资料里出现过就默认使用
这些对象不作为本页可生成业务流程不要因为源资料里出现过就默认生成连接、认证、网络访问、Web 请求响应或会话管理代码。
## 禁止项
- 不要直接把 `new TStream()` 写成普通脚本里的可靠创建方式。
- 不要无参创建 `TCipher`;最小可靠写法是 `new TCipher(2)` 后再设置 `Password`
- 不要把 `TWebRequest` / `TWebResponse` 写进普通脚本模板。
- 不要把 `MailMsg.AddText(...)` 当成默认消息正文写法;普通正文优先设置 `Body`
- 不要在缺少主机、账号、密码、端口和协议要求时生成 `FTP` / `SMTP` / `POP3` 连接流程。
- 不要把未写入文档资料里的内置对象,当成语法事实。
- 不要把本页反例块里的失败创建代码包进 `try/except` 后当成业务模板。

View File

@ -6,19 +6,23 @@
是否含不可照写反例:是
遇到不确定时:先按本页候选页继续判断;[12_matrix_and_collections.md](12_matrix_and_collections.md)、[23_fmarray.md](23_fmarray.md);仍不命中时回到语法路由中心 [index.md](index.md);如果问题已经超出语法层,回到 TSL 总入口 [../index.md](../index.md)
这一篇只讲矩阵专用语法主干:矩阵初始化、数列构造、矩阵逆/广义逆,以及怎样读取矩阵的行列大小和索引。它和 [12_matrix_and_collections.md](12_matrix_and_collections.md) 的分工是:`13` 只讲数组与矩阵样数据,这一篇讲矩阵专用构造、运算与大小接口。
这一篇只讲矩阵专用语法主干:矩阵初始化、数列构造、矩阵逆/广义逆、矩阵尺寸与索引、矩阵遍历、子矩阵和 `mfind` 查找。它和 [12_matrix_and_collections.md](12_matrix_and_collections.md) 的分工是:`12` 讲普通数组与集合关系,这一篇讲矩阵专用构造、遍历、子矩阵和矩阵查找接口。
## 本篇职责
回答“怎样直接构造全零矩阵、全一矩阵、随机矩阵、单位矩阵、空矩阵和数列数组,怎样写矩阵逆/广义逆,以及怎样拿到矩阵的行数、列数、行索引和列索引”。
回答“怎样直接构造全零矩阵、全一矩阵、随机矩阵、单位矩阵、空矩阵和数列数组,怎样写矩阵逆/广义逆,怎样拿到矩阵的行数、列数、行索引和列索引,怎样遍历矩阵、取/改子矩阵,以及怎样用 `mfind` 找到或替换符合条件的单元格”。
## 智能体矩阵深水判断流程
1. 先判断要写矩阵初始化、数列构造、矩阵逆/广义逆,还是矩阵尺寸与索引读取
1. 先判断要写矩阵初始化、数列构造、矩阵逆/广义逆、矩阵尺寸与索引读取、矩阵遍历、子矩阵,还是 `mfind` 查找/替换
2. 基础数组和矩阵样比较先回看 `12_matrix_and_collections.md`
3. `mrows` / `mcols` / `msize` 等函数只照文档返回形态写。
4. 不要把列索引数组误当成单个数字。
5. 没有对应代码块时不要发明矩阵深水写法。
4. 需要逐单元执行语句块时用 `matrix::begin ... end`;需要把表达式结果写回每个单元时用 `matrix ::= expression`
5. 需要遍历到嵌套数组最深层时用 `matrix:.begin ... end``matrix:.= expression`
6. 子矩阵范围使用 `row_start:row_end`、`:`、下标数组和列范围组合;不要把字符串键当作子矩阵范围序号。
7. `mfind(...)` 用于把符合条件的单元格转换成下标列表,或同时返回原值/替换原值。
8. 不要把列索引数组误当成单个数字。
9. 没有对应代码块时不要发明矩阵深水写法。
## 核心规则
@ -35,6 +39,19 @@
- `msize(matrix_value, 1)` 返回行索引数组和列索引数组。
- `mrows(matrix_value)` / `mcols(matrix_value)` 默认返回数量;第二个参数写成 `1` 时返回索引数组。
- `mrows(matrix_value, 1)` / `mcols(matrix_value, 1)` 的返回值可用于索引匹配;不要把它们当成数量。
- `matrix::begin ... end` 是矩阵遍历语句块,最多按二维遍历;语句块里可用 `mcell`、`mrow`、`mcol`。
- `matrix ::= expression` 是矩阵遍历赋值,把表达式结果逐单元写回原矩阵;它不是语句块。
- `matrix:.begin ... end` 是深度遍历语句块;对嵌套数组会遍历到最深节点。
- `matrix:.= expression` 是深度遍历赋值;需要对不规则嵌套数组逐叶子节点写回时使用。
- 遍历时需要维度信息可用 `mIndexCount`;需要第 `n` 维下标可用 `mIndex(n)`
- 子矩阵提取可以写 `matrix[row_start:row_end, col_start:col_end]`、`matrix[:, col_range]`、`matrix[row_index_array, col_index_array]`。
- 子矩阵赋值可以写成单个标量,也可以写成同结构矩阵;赋值矩阵应和目标子矩阵形状匹配。
- 子矩阵也可以接 `::=` 做逐单元赋值。
- `mfind(matrix)` 返回真值单元格下标;一维数组的无条件 `mfind` 返回一维下标数组。
- `mfind(matrix, condition)` 返回符合条件的下标行;二维矩阵下每行形如 `array(row_index, col_index)`
- `mfind(matrix, condition, 1)` 在每个下标行末尾追加原单元值。
- `mfind(matrix, condition, ret_value, replacement)` 会把符合条件的单元格替换成 `replacement`,并返回替换前的匹配信息。
- `mfindSparse(matrix, condition)` 用于嵌套数组或稀疏结构,返回包含完整深层路径的下标行。
## 可直接照写示例
@ -205,6 +222,311 @@ col_index := mcols(matrix_rows, 1);
- `mcols(matrix_rows)` 返回 `2`
- `mcols(matrix_rows, 1)` 返回 `array("A", "B")`
### 矩阵遍历:`::` 与 `::=`
`::` 执行语句块:
代码块身份:可直接照写示例
```tsl
matrix_value := array((1, 2, 3), (4, 5, 6));
sum_value := 0;
matrix_value::begin
sum_value += mcell;
end
writeLn(sum_value);
```
代码块身份:输出片段
```text
21
```
`::=` 把表达式结果逐单元写回:
代码块身份:可直接照写示例
```tsl
matrix_value := array((1, 2), (3, 4));
matrix_value ::= mrow * 10 + mcol;
writeLn(matrix_value[0][0]);
writeLn(matrix_value[0][1]);
writeLn(matrix_value[1][0]);
writeLn(matrix_value[1][1]);
```
代码块身份:输出片段
```text
0
1
10
11
```
说明:
- `mcell` 是当前单元格值。
- `mrow` 是当前行下标。
- `mcol` 是当前列下标。
- `::=` 右侧写表达式,不写 `begin ... end` 语句块。
### 深度遍历:`:.` 与 `:.=`
`:.` 会遍历到嵌套数组的最深节点:
代码块身份:可直接照写示例
```tsl
nested_value := array(10, 12, ("A": array(30), "B": 22), ("A": array(31, 32), "B": 23));
deep_count := 0;
nested_value:.begin
deep_count += 1;
end
writeLn(deep_count);
```
代码块身份:输出片段
```text
7
```
`:.=` 会把表达式结果写回最深节点:
代码块身份:可直接照写示例
```tsl
values := array(-1, 2, -3);
values:.= abs(mcell);
writeLn(values[0]);
writeLn(values[1]);
writeLn(values[2]);
```
代码块身份:输出片段
```text
1
2
3
```
### 子矩阵
按行列范围提取:
代码块身份:可直接照写示例
```tsl
matrix_value := array((1, 2, 3), (4, 5, 6), (7, 8, 9));
sub_value := matrix_value[1:2, 0:1];
writeLn(mrows(sub_value));
writeLn(mcols(sub_value));
writeLn(sub_value[0][0]);
writeLn(sub_value[0][1]);
writeLn(sub_value[1][0]);
writeLn(sub_value[1][1]);
```
代码块身份:输出片段
```text
2
2
4
5
7
8
```
按下标数组提取:
代码块身份:可直接照写示例
```tsl
matrix_value := array((1, 2, 3), (4, 5, 6), (7, 8, 9));
sub_value := matrix_value[array(0, 2), array(1, 2)];
writeLn(sub_value[0][0]);
writeLn(sub_value[0][1]);
writeLn(sub_value[1][0]);
writeLn(sub_value[1][1]);
```
代码块身份:输出片段
```text
2
3
8
9
```
子矩阵赋值:
代码块身份:可直接照写示例
```tsl
matrix_value := array((1, 2, 3), (4, 5, 6), (7, 8, 9));
matrix_value[0:1, 1:2] := array((10, 11), (12, 13));
writeLn(matrix_value[0][1]);
writeLn(matrix_value[0][2]);
writeLn(matrix_value[1][1]);
writeLn(matrix_value[1][2]);
```
代码块身份:输出片段
```text
10
11
12
13
```
子矩阵逐单元赋值:
代码块身份:可直接照写示例
```tsl
matrix_value := array((1, 2), (3, 4));
matrix_value[0:1, 0:1] ::= mrow * 10 + mcol;
writeLn(matrix_value[0][0]);
writeLn(matrix_value[0][1]);
writeLn(matrix_value[1][0]);
writeLn(matrix_value[1][1]);
```
代码块身份:输出片段
```text
0
1
10
11
```
### `mfind``mfindSparse`
一维数组无条件查找会返回一维下标数组:
代码块身份:可直接照写示例
```tsl
values := array(1, 0, 2, 0, 3);
indexes := mfind(values);
writeLn(length(indexes));
writeLn(indexes[0]);
writeLn(indexes[1]);
writeLn(indexes[2]);
```
代码块身份:输出片段
```text
3
0
2
4
```
二维矩阵按条件查找:
代码块身份:可直接照写示例
```tsl
matrix_value := array((1, 0), (2, 3));
indexes := mfind(matrix_value, mcell >= 2);
writeLn(length(indexes));
writeLn(indexes[0][0]);
writeLn(indexes[0][1]);
writeLn(indexes[1][0]);
writeLn(indexes[1][1]);
```
代码块身份:输出片段
```text
2
1
0
1
1
```
第三个参数写成 `1` 时,每行末尾追加原单元值:
代码块身份:可直接照写示例
```tsl
matrix_value := array((1, 0), (2, 3));
matches := mfind(matrix_value, mcell >= 2, 1);
writeLn(matches[0][0]);
writeLn(matches[0][1]);
writeLn(matches[0][2]);
writeLn(matches[1][0]);
writeLn(matches[1][1]);
writeLn(matches[1][2]);
```
代码块身份:输出片段
```text
1
0
2
1
1
3
```
第四个参数用于替换符合条件的单元格:
代码块身份:可直接照写示例
```tsl
matrix_value := array((1, 0), (2, 3));
matches := mfind(matrix_value, mcell >= 2, 1, 100);
writeLn(matches[0][2]);
writeLn(matches[1][2]);
writeLn(matrix_value[1][0]);
writeLn(matrix_value[1][1]);
```
代码块身份:输出片段
```text
2
3
100
100
```
`mfindSparse` 返回深层路径:
代码块身份:可直接照写示例
```tsl
nested_value := array(10, ("A": 0, "B": array(2)), 0);
indexes := mfindSparse(nested_value, mcell = 2);
writeLn(length(indexes));
writeLn(length(indexes[0]));
writeLn(indexes[0][0]);
writeLn(indexes[0][1]);
writeLn(indexes[0][2]);
```
代码块身份:输出片段
```text
1
3
1
B
0
```
## 默认生成模板
需要矩阵构造时,优先从这个最短模板开始:
@ -222,6 +544,9 @@ matrix_value := zeros(2, 3);
- 以为 `mrows(matrix_value, 1)``mcols(matrix_value, 1)` 返回的还是数量。
- 写带步长的 `->` 时,漏掉外层 `array(...)`
- 还在普通数组页里硬塞矩阵专用大小接口。
- 把 `::=` 写成带 `begin ... end` 的语句块。
- 用 `::` 期待遍历到任意深度;深度遍历使用 `:.`
- 子矩阵赋值时用形状不匹配的矩阵硬塞。
代码块身份:反例 / 不可照写