Files
tsl-devkit/docs/tsl/syntax/27_fmarray.md
T
csh 3d83740f88 Squashed 'docs/standards/playbook/' changes from c3f8137..25d895d
25d895d 🐛 fix(gitea_workflow): clean up temp repos after job steps
2bc3b11 🐛 fix(gitea_workflow): clean up temporary repo dirs in workflows
98c3f30 📝 docs(agent_rules): allow plan execution on current branch
16c7230 📝 docs(prompts): define custom verify layering
8efc4dd 🐛 fix(skills): quote commit-message description
bc8498f 🐛 fix(ci): install tomli for gitea tests
55cda3b 🐛 fix(tests): report missing toml parser clearly
c0729c7 🐛 fix(playbook): import Optional for cli compatibility
63e24bf 📦 deps(skills): sync thirdparty skills
d2f9356 🐛 fix(ci): isolate gitea workflow repos
588b81d 🐛 fix(ci): inline gitea workflow bootstrap
e0b1c3a ♻️ refactor(skills): standardize first-party skill contracts
2c5050d ♻️ refactor(skills): rename repo skills source dir
f049dfb 📦 deps(skills): drop duplicate first-party superpowers skills
234b335  feat(workflow): add superpowers planning and execution state tracking
c1702a6 📝 docs(markdown): format tracked markdown and drop stale templates
2325409 📝 docs(markdown): clarify optional markdownlint usage
214c44e 🔧 chore(markdown): add markdownlint baseline and lint fixes
a22b324 📝 docs(templates): add execution and memory-bank prompt templates
223a797 📝 docs(templates): update README for Claude Code and current features
4ac8672 📝 docs: simplify README + platform-agnostic tools + auto-create local rules
2431c9d 📝 docs: add claude_md config and use cross-platform paths
d64b248 📝 docs: fix README.md inaccuracies and add Claude Code info
c8d6bf2 🐛 fix(playbook): use relative paths in CLAUDE.md when not at project root
6518f0f  feat(playbook): auto-create CLAUDE.md with path discovery
6ec9a45  feat(skills): add skill_link symlink support + platform-agnostic prompt
9f8b6b5 📝 docs: update README and config example for Claude Code support
79cff6c 📝 docs(skills): add Claude Code platform support
452c6f5  feat(playbook): auto-inject AGENTS.md into CLAUDE.md
e1dbf3c 🐛 fix(skills): remove dual-path from commit-message skill
f3a7259 🔧 chore(ci): use prepare_repo.sh in both workflows
da08212 🔧 chore(ci): extract prepare_repo.sh and clean up workflows
7ade85e 🗑️ remove(tsl): drop syntax_book/, data/ source and build script
f94dba0 ♻️ refactor(skills): update playbook.py and tests for thirdparty/ layout
b3df412 ♻️ refactor(skills): separate thirdparty skills into thirdparty/ subdirectory
64950e7 📦 deps(skills): sync thirdparty skills
a2e3cb0  feat(playbook): add no_backup deploy controls
8609d59 🐛 fix(docs): repair reference catalog source links
956da11 🐛 fix(playbook): publish hidden ci test fixes
3f67754 📦 deps(skills): sync thirdparty skills
08ca87b 📦 deps(skills): add karpathy thirdparty sync
96b705b 📝 docs(tsl): rebuild canonical syntax and routing manual
3ed5052 📦 deps(skills): sync thirdparty skills
60108dd 📦 deps(skills): sync thirdparty skills
da85d4e 🐛 fix(thirdparty): prune nested project snapshots
a2a697e 📦 deps(skills): sync thirdparty skills
9df610a 🐛 fix(thirdparty): exclude duplicated superpowers skills
33dd5bb 🐛 fix(thirdparty): preserve optional manifest fields
91b0ea7 🐛 fix(thirdparty): preserve manifest during snapshot update
2e26f98 🔧 chore(thirdparty): generalize skills sync pipeline
5b9c1e3 📦 deps(skills): sync superpowers
2f2d34a 📝 docs(readme): normalize subtree command spacing
62db7db 🐛 fix(ci): serialize superpowers update and sync
3463223 🐛 fix(ci): use literal superpowers sync paths
48f6de8 📦 deps(skills): sync superpowers
4b23529 🔧 chore(ci): merge superpowers update and sync workflow
a56d75b 📦 deps(skills): sync superpowers
84bcefa 🔧 chore(ci): use ci[bot] commit author name
00a07e5 📦 deps(skills): sync superpowers
7b84daf 🐛 fix(templates): enforce main loop progress tracking
51373d7 🔧 chore(ci): automate superpowers sync workflow
eaaa39c 🐛 fix(ci): prevent stale superpowers sync from restoring skills block
79755c6 📦 deps(skills): sync superpowers
836d878 📦 deps(skills): sync superpowers
8216c9f 📦 deps(skills): sync superpowers
9439505 🐛 fix(playbook): address reported repo issues

git-subtree-dir: docs/standards/playbook
git-subtree-split: 25d895d8b3f56624ccfe99ad7289e9eb49e0f316
2026-05-24 13:04:14 +08:00

536 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FMArray
文档类型:语法主线
是否可直接用于生成代码:是
是否含已验证可执行示例:是
是否含已验证反例:是
遇到不确定时跳转到:[26_matrix_deep_dive.md](26_matrix_deep_dive.md)、[13_matrix_and_collections.md](13_matrix_and_collections.md)、[28_ts_sql_core.md](28_ts_sql_core.md)
手册位置:第 27 篇,共 32 篇。上一篇:[26_matrix_deep_dive.md](26_matrix_deep_dive.md)。下一篇:[28_ts_sql_core.md](28_ts_sql_core.md)。
这一篇只讲当前解释器下已经实际跑通的 `FMArray` 主干能力:怎样构造 `FMArray`、怎样判断类型、怎样和 `Array` 互转、怎样读取尺寸、做基础运算、做多维转置与维度交换、做矩阵连接、参与 `select/mselect`,以及当前可用的 `insert/delete/update` 语法边界。
## 这一篇解决什么问题
回答“什么时候该用 `FMArray` 而不是普通 `array`,以及当前解释器里最可靠的 `FMArray` 写法到底有哪些”。
## 必须记住的规则
- `fmarray[...]` 可以直接构造 `FMArray` 常量。
- `datatype(v)``FMArray` 返回 `27`
- `datatype(v, 1)` 可以读出 `FMArray` 单元格类型;当前已验证到 `0` 整型、`1` 浮点、`20` 64 位整型。
- `ifFMArray(v)` 可直接判断值是否为 `FMArray`
- `MInit``MInitDiag``MRand` 都可直接生成 `FMArray`
- `ArrayToFM``MatrixToArray` 可在 `Array` / `FMArray` 间互转。
- `MSize``MRows``MCols` 都支持 `FMArray`;对三维 `FMArray``MSize` 已验证会返回全部维度长度。
- `FMArray` 已验证支持和标量、`FMArray``Array` 做基础算符运算。
- `union2` 已验证支持 `FMArray` / `Array` 混合运算;结果类型跟随左值。
- 对超过二维的 `FMArray`,反引号转置会把全部维度倒置;`mswap` 可只交换指定维度。
- `union` 可做按行连接且不去重,但列结构必须兼容。
- `|``:|` 都可做按列连接;当前已验证到行数不一致时会用 `0` 补齐,并且两者表现一致。
-`FMArray` 做普通 `select` 不会保留 `FMArray` 类型;`mselect` 也不会返回 `datatype=27`
- 当前实测里,`insert into a array(...)``delete from a where ...;``update a set ... where ... end;` 都能作用于 `FMArray`,但三者的收尾形式并不完全相同。
## 已验证语法
### 常量构造与类型判断
代码块身份:已验证可执行示例
```tsl
program test;
begin
f1 := fmarray[1, 2, 3];
f2 := fmarray[[1, 2], [3, 4]];
f3 := fmarray[1.0, 2.0, 3.5];
WriteLn(datatype(f1));
WriteLn(datatype(f1, 1));
WriteLn(datatype(f3, 1));
WriteLn(ifFMarray(f1));
WriteLn(length(f1));
WriteLn(f1[0], ',', f1[1], ',', f1[2]);
WriteLn(mrows(f2));
WriteLn(mcols(f2));
WriteLn(f2[0,0], ',', f2[0,1], ',', f2[1,0], ',', f2[1,1]);
end.
```
已验证运行结果:
- `datatype(f1)` 返回 `27`
- `datatype(f1, 1)` 返回 `0`
- `datatype(f3, 1)` 返回 `1`
- `ifFMarray(f1)` 返回 `1`
- `length(f1)` 返回 `3`
- `f1` 的三个元素依次是 `1``2``3`
- `f2` 的行数是 `2`、列数是 `2`
- `f2` 四个单元依次是 `1``2``3``4`
### `MInit`、`MInitDiag`、`MRand`
代码块身份:已验证可执行示例
```tsl
program test;
begin
fm1 := MInit(5, 3);
fm2 := MInit(array(3, 2), 1L);
fd1 := MInitDiag(3, 3, 1);
fr1 := MRand(2, 3);
WriteLn(datatype(fm1, 1));
WriteLn(length(fm1));
WriteLn(fm1[0], ',', fm1[1], ',', fm1[2], ',', fm1[3], ',', fm1[4]);
WriteLn(datatype(fm2, 1));
WriteLn(mrows(fm2));
WriteLn(mcols(fm2));
WriteLn(fd1[0,0], ',', fd1[0,1], ',', fd1[1,0], ',', fd1[1,1], ',', fd1[2,2]);
WriteLn(mrows(fr1));
WriteLn(mcols(fr1));
end.
```
已验证运行结果:
- `MInit(5, 3)` 生成长度为 `5` 的整型 `FMArray`,五个元素都是 `3`
- `datatype(fm1, 1)` 返回 `0`
- `MInit(array(3, 2), 1L)` 的单元格类型是 `20`
- `fm2` 的行数是 `3`、列数是 `2`
- `MInitDiag(3, 3, 1)``(0,0)``(1,1)``(2,2)``1`,而 `(0,1)``(1,0)``0`
- `MRand(2, 3)` 的行数是 `2`、列数是 `3`
### `ArrayToFM`、`MatrixToArray` 与单元格类型转换
代码块身份:已验证可执行示例
```tsl
program test;
begin
a1 := array(1, 2, 3.5);
f1 := ArrayToFM(a1, 0);
f2 := ArrayToFM(a1, 0.0);
f3 := int64(fmarray[1, 2, 3]);
a2 := MatrixToArray(fmarray[[1, 2], [3, 8]]);
WriteLn(datatype(f1, 1));
WriteLn(f1[0], ',', f1[1], ',', f1[2]);
WriteLn(datatype(f2, 1));
WriteLn(f2[0], ',', f2[1], ',', f2[2]);
WriteLn(datatype(f3, 1));
WriteLn(f3[0], ',', f3[1], ',', f3[2]);
WriteLn(mrows(a2));
WriteLn(mcols(a2));
WriteLn(a2[0][0], ',', a2[0][1], ',', a2[1][0], ',', a2[1][1]);
end.
```
已验证运行结果:
- `ArrayToFM(a1, 0)` 的单元格类型是 `0`,结果是 `1,2,3`
- `ArrayToFM(a1, 0.0)` 的单元格类型是 `1`,结果是 `1,2,3.5`
- `int64(fmarray[1, 2, 3])` 的单元格类型是 `20`
- `MatrixToArray(fmarray[[1, 2], [3, 8]])` 返回一个 `2 x 2``Array`,内容是 `(1,2)``(3,8)`
### 尺寸与重构
二维和三维尺寸:
代码块身份:已验证可执行示例
```tsl
program test;
begin
f3 := fmarray[[[1, 1], [2, 2], [3, 3]], [[2, 2], [3, 3], [4, 4]]];
s := MSize(f3);
WriteLn(length(s));
WriteLn(s[0], ',', s[1], ',', s[2]);
end.
```
已验证运行结果:
- `MSize(f3)` 的长度是 `3`
- 三个维度依次是 `2``3``2`
`reshape` 会保持 `FMArray` 类型:
代码块身份:已验证可执行示例
```tsl
program test;
begin
f1 := fmarray[[1, 2], [3, 4], [5, 5]];
r1 := reshape(f1, 6);
WriteLn(datatype(r1));
WriteLn(length(r1));
WriteLn(r1[0], ',', r1[1], ',', r1[2], ',', r1[3], ',', r1[4], ',', r1[5]);
end.
```
已验证运行结果:
- `datatype(r1)` 仍然是 `27`
- `r1` 的长度是 `6`
- 元素依次是 `1``2``3``4``5``5`
### 标量运算与基础算符
代码块身份:已验证可执行示例
```tsl
program test;
begin
f1 := fmarray[1, 2, 3];
f2 := fmarray[2, 3, 4];
a1 := array(2, 3, 4);
s0 := f1 + 1;
s1 := f1 + f2;
s2 := f1 + a1;
WriteLn(datatype(s0));
WriteLn(s0[0], ',', s0[1], ',', s0[2]);
WriteLn(datatype(s1));
WriteLn(s1[0], ',', s1[1], ',', s1[2]);
WriteLn(datatype(s2));
WriteLn(s2[0], ',', s2[1], ',', s2[2]);
end.
```
已验证运行结果:
- `f1 + 1``datatype``27`,结果是 `2,3,4`
- `f1 + f2``datatype``27`,结果是 `3,5,7`
- `f1 + array(2, 3, 4)``datatype` 仍是 `27`,结果也是 `3,5,7`
### `union2` 与左值类型
代码块身份:已验证可执行示例
```tsl
program test;
begin
f1 := fmarray[1, 2, 0, 4, 5];
a1 := array(1, 0, 7.2);
u1 := f1 union2 a1;
u2 := a1 union2 f1;
WriteLn(datatype(u1));
WriteLn(datatype(u1, 1));
WriteLn(length(u1));
WriteLn(u1[0], ',', u1[1], ',', u1[2], ',', u1[3], ',', u1[4], ',', u1[5]);
WriteLn(datatype(u2));
WriteLn(length(u2));
WriteLn(u2[0], ',', u2[1], ',', u2[2], ',', u2[3], ',', u2[4], ',', u2[5]);
end.
```
已验证运行结果:
- `union2` 的结果 `datatype``27`
- `f1 union2 array(1, 0, 7.2)` 的单元格类型会提升为 `1` 浮点型
- `f1 union2 array(1, 0, 7.2)` 的长度是 `6`,结果是 `1,2,0,4,5,7.2`
- `array(1, 0, 7.2) union2 f1``datatype``5`
- `array(1, 0, 7.2) union2 f1` 的长度也是 `6`,结果是 `1,0,7.2,2,4,5`
### 多维转置与维度交换
三维 `FMArray` 上,反引号转置会把全部维度倒置:
代码块身份:已验证可执行示例
```tsl
program test;
begin
f3 := fmarray[[[1], [2]], [[1], [0]], [[3], [-8]]];
t := `f3;
s := MSize(t);
WriteLn(datatype(t));
WriteLn(length(s));
WriteLn(s[0], ',', s[1], ',', s[2]);
WriteLn(t[0,0,0], ',', t[0,0,1], ',', t[0,0,2], ';', t[0,1,0], ',', t[0,1,1], ',', t[0,1,2]);
end.
```
已验证运行结果:
- 原矩阵尺寸是 `3,2,1`,转置后尺寸是 `1,2,3`
- 结果 `datatype` 仍是 `27`
- 转置后的内容是 `[[[1,1,3],[2,0,-8]]]`
只交换指定维度时,使用 `mswap`
代码块身份:已验证可执行示例
```tsl
program test;
begin
f3 := fmarray[[[1], [2]], [[1], [0]], [[3], [-8]]];
t := mswap(f3, 0, 1);
s := MSize(t);
WriteLn(datatype(t));
WriteLn(length(s));
WriteLn(s[0], ',', s[1], ',', s[2]);
WriteLn(t[0,0,0], ',', t[0,1,0], ',', t[0,2,0], ';', t[1,0,0], ',', t[1,1,0], ',', t[1,2,0]);
end.
```
已验证运行结果:
- `mswap(f3, 0, 1)` 后尺寸是 `2,3,1`
- 结果 `datatype` 仍是 `27`
- 结果内容是 `[[[1],[1],[3]],[[2],[0],[-8]]]`
### 矩阵连接:`union`、`|`、`:|`
`union` 会按行拼接,不做去重:
代码块身份:已验证可执行示例
```tsl
program test;
begin
t1 := fmarray[[1, 2], [3, 4], [5, 5]];
t2 := fmarray[[7, 8]];
u := t1 union t2;
WriteLn(datatype(u));
WriteLn(mrows(u));
WriteLn(mcols(u));
WriteLn(u[0,0], ',', u[0,1], ';', u[1,0], ',', u[1,1], ';', u[2,0], ',', u[2,1], ';', u[3,0], ',', u[3,1]);
end.
```
已验证运行结果:
- `union` 的结果 `datatype``27`
- `t1 union t2` 的行数是 `4`、列数是 `2`
- 拼接后四行依次是 `(1,2)``(3,4)``(5,5)``(7,8)`
`|``:|` 会按列拼接:
代码块身份:已验证可执行示例
```tsl
program test;
begin
t1 := fmarray[[1, 2], [3, 4], [5, 5]];
t2 := fmarray[[3, 4], [7, 8], [6, 9]];
u1 := t1 | t2;
u2 := t1 :| t2;
WriteLn(datatype(u1));
WriteLn(mrows(u1));
WriteLn(mcols(u1));
WriteLn(u1[0,0], ',', u1[0,1], ',', u1[0,2], ',', u1[0,3]);
WriteLn(u1[1,0], ',', u1[1,1], ',', u1[1,2], ',', u1[1,3]);
WriteLn(u1[2,0], ',', u1[2,1], ',', u1[2,2], ',', u1[2,3]);
WriteLn(u2[0,0], ',', u2[0,1], ',', u2[0,2], ',', u2[0,3]);
WriteLn(u2[1,0], ',', u2[1,1], ',', u2[1,2], ',', u2[1,3]);
WriteLn(u2[2,0], ',', u2[2,1], ',', u2[2,2], ',', u2[2,3]);
end.
```
已验证运行结果:
- `|` 的结果 `datatype``27`
- `t1 | t2``t1 :| t2` 的行数都是 `3`、列数都是 `4`
- 两种写法的结果都依次是 `(1,2,3,4)``(3,4,7,8)``(5,5,6,9)`
当前还额外验证到:行数不一致时,`|``:|``FMArray` 上表现一致,缺失行会用 `0` 补齐。
- `fmarray[[1, 2], [3, 4], [5, 5]] | fmarray[[3, 4]]` 的结果三行依次是 `(1,2,3,4)``(3,4,0,0)``(5,5,0,0)`
- `fmarray[[3, 4]] | fmarray[[1, 2], [3, 4], [5, 5]]` 的结果三行依次是 `(3,4,1,2)``(0,0,3,4)``(0,0,5,5)`
- 把上面两条里的 `|` 改成 `:|`,结果一致
### 排序
一维排序:
代码块身份:已验证可执行示例
```tsl
program test;
begin
s1 := fmarray[10, 2, -3, 8];
sortarray(s1);
WriteLn(s1[0], ',', s1[1], ',', s1[2], ',', s1[3]);
end.
```
已验证运行结果:
- 排序后结果是 `-3,2,8,10`
二维按字段排序:
代码块身份:已验证可执行示例
```tsl
program test;
begin
f1 := fmarray[[11, 12], [31, 4], [5, 5]];
SortTableByField(f1, 0, 1);
WriteLn(f1[0,0], ',', f1[0,1], ';', f1[1,0], ',', f1[1,1], ';', f1[2,0], ',', f1[2,1]);
end.
```
已验证运行结果:
- 排序后依次是 `(5,5)``(11,12)``(31,4)`
### TS-SQL 对 `FMArray` 的支持
代码块身份:已验证可执行示例
```tsl
program test;
begin
q1 := select * from fmarray[[1, 2], [0, 4], [1, 2], [5, 6]] end;
q2 := mselect * from fmarray[[1, 2], [0, 4], [1, 2], [5, 6]] end;
WriteLn(datatype(q1));
WriteLn(mrows(q1));
WriteLn(datatype(q2));
WriteLn(mrows(q2));
WriteLn(mcols(q2));
end.
```
已验证运行结果:
- 普通 `select` 的返回 `datatype``5`
- `q1` 的行数是 `4`
- `mselect` 的返回 `datatype``17`
- `q2` 的行数是 `4`、列数是 `2`
- 说明当前解释器下,对 `FMArray` 做 TS-SQL 查询时,结果不会保留 `datatype=27`
### `insert` / `delete` / `update`
`insert`
代码块身份:已验证可执行示例
```tsl
program test;
begin
a := MInit(2, 3, 1.0);
insert into a array(9);
WriteLn(mrows(a));
WriteLn(mcols(a));
WriteLn(a[2,0], ',', a[2,1], ',', a[2,2]);
end.
```
已验证运行结果:
- 插入后行数是 `3`
- 列数仍是 `3`
- 新插入的第三行是 `9,9,9`
`delete`
代码块身份:已验证可执行示例
```tsl
program test;
begin
d := fmarray[[1, 2], [0, 4], [5, 6]];
delete from d where [1] = 4;
WriteLn(mrows(d));
WriteLn(d[0,0], ',', d[0,1], ';', d[1,0], ',', d[1,1]);
end.
```
已验证运行结果:
- 删除后行数是 `2`
- 保留的两行是 `(1,2)``(5,6)`
`update`
代码块身份:已验证可执行示例
```tsl
program test;
begin
u := fmarray[[1, 2], [0, 4], [5, 6]];
update u set [0] = 100 where [1] = 4 end;
WriteLn(mrows(u));
WriteLn(u[0,0], ',', u[0,1], ';', u[1,0], ',', u[1,1], ';', u[2,0], ',', u[2,1]);
end.
```
已验证运行结果:
- 更新后行数仍是 `3`
- 结果三行依次是 `(1,2)``(100,4)``(5,6)`
当前解释器下,这三种写法的收尾形式已验证为:
- `insert into a array(9);`
- `delete from d where [1] = 4;`
- `update u set [0] = 100 where [1] = 4 end;`
## 暂不在本页展开的部分
- `MInitDiag` 更高维行为
- `MRand` 的随机分布参数变体
- `union` / `|` / `:|` 与普通 `array` 的更多混合边界
- `left join` / `right join` / 更复杂 SQL 写回
- CopyOnWrite 的内存级行为
这些都要等单独补最小验证后,再进入主线正文。
## 最小可编译示例
如果你只想先记住最短 `FMArray` 骨架,从这个开始:
代码块身份:已验证可执行示例
```tsl
f := fmarray[1, 2, 3];
```
## 常见误写
- 在一个 `FMArray` 常量里混用不同单元格类型。
-`FMArray` 当成支持字符串下标的 `array`
- 以为对 `FMArray` 做普通 `select` 后,结果还是 `datatype=27`
-`delete``update` 的结尾形式写成同一种。
- 以为 `union` 可以忽略列结构差异。
- 以为 `array union2 fmarray` 还会返回 `FMArray`
代码块身份:反例 / 不可照写
```text
f := fmarray[1, 2.0, 3];
```
上面这种写法在当前解释器里会编译失败,错误信息包含 `fmarray must be same type`
代码块身份:反例 / 不可照写
```text
f := fmarray[1, 2, 3];
WriteLn(f["A"]);
```
上面这种写法在当前解释器里会运行报错,错误信息包含 `fmarray index type error`
代码块身份:反例 / 不可照写
```text
delete from d where [1] = 4 end;
```
这类写法不要直接当成当前默认模板。当前解释器下,我实测 `delete ... end;` 会报 `Statement missing terminator`;已验证可用的是 `delete ...;`
代码块身份:反例 / 不可照写
```text
t1 := fmarray[[1, 2], [3, 4]];
t2 := fmarray[[7, 8, 9]];
u := t1 union t2;
```
上面这种写法会运行报错,错误信息包含 `union dim dismatch`。当前已验证的 `union` 只适用于列结构兼容的 `FMArray`
## 跳转指引
- 回看矩阵基础:见 [26_matrix_deep_dive.md](26_matrix_deep_dive.md)
- 看 TS-SQL 基础:见 [28_ts_sql_core.md](28_ts_sql_core.md)
- 看 TS-SQL 进阶:见 [29_ts_sql_advanced.md](29_ts_sql_advanced.md)