📝 docs(tsl-syntax-reference): document verified facts from FAQ corpus
从 FAQ 语料(2018 篇镜像)与参考页做完 169 条逐条差集,补入 6 组此前未收录的语言 事实。每条先用 TSL.exe 实跑观察行为,再收敛成 39 条断言的回归门,在 TSLGen2、 AnalyseNG.NET、TSL 三个解释器上均通过后才写入。 - 16 页:0/0 得 nan、2/0 得 inf;nan 的 = > < >= <= 恒假而 <> 为真;nan 沿算术 传播;nil 在乘除减里按 0 参与 - 04 页:整体赋值免声明,但对未建立的变量写单元格赋值会报「变量类型不是Array」 - 07 页:相邻两个 if 是两条独立语句都会执行;for..in 单控制变量拿到的是键不是值; 二维数组按行推进,行本身是数组(新增 syntax-07-013) - 21 页:子矩阵赋值语句求值为 0;t[:,:] 按位置复制不按列名对齐(新增 syntax-21-019);| 列并时同名字符串列键由右操作数覆盖(新增 syntax-21-018) - 13 页:select 输出列表同名列后者覆盖前者,须用 as 改名(新增 syntax-13-032) 三条 FAQ 说法实跑不复现,故未写入:12574 的括号消歧、19857 的 -2147483648 字面量限制、31474 的 :. bugfix 记录。15305/11045 的用户/公用/共享函数同名解析 优先级需要服务端多账号环境,本地无法验证,仍为已知缺口。 lexicon.json 为 16 页补两个页级 alias,使 nan/nil 语义能被自然语言查询命中。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
- 多表联接中,`thisRow(表序号)` 和 `thisRowIndex(表序号)` 分别取得指定来源表的当前整行与原始下标。
|
||||
- 联接类型:`left join` 保留左表、`right join` 保留右表、`full join` 保留双方、`cross join` 笛卡尔积、逗号联接等价于 `cross join`;不匹配处用 `nil` 填充。
|
||||
- `select` 列表支持 `distinct` 去重、`as 别名`、`as nil`(参与计算但不返回)、`起始列 to 结束列` 字段区间、`selectopt(位选项)`、`drange(区间/M of N)`。
|
||||
- `select` 输出列表里出现同名列时,靠后的列会覆盖靠前的,结果集里只留一列;多表 `join` 两侧有同名字段时尤其容易踩。要两列都保留,用 `as` 给其中一个改名。
|
||||
- 聚集函数统一形态 `Func(Expr[, Cond[, N[, MovingFirst[, CacheId]]]])`:条件聚集、移动聚集、多字段聚集、`refof(Expr, N)` 引用相对行;`aggof('名', Expr)` 调用自定义聚集回调。
|
||||
- `thisGroup` 不是普通值,而是分组后的子结果集;要通过子 `select` / `vselect` 的 `from thisGroup` 来访问。
|
||||
- `thisRowIndex` 在 `order by` 之后仍可返回原始行位置;`thisOrder` 返回排序后的自然排名。
|
||||
@@ -699,6 +700,48 @@ writeLn(mcols(range_rows));
|
||||
- `表达式 as nil` 让该列只参与临时计算,不出现在结果集里(上例 `nil_rows` 只剩 `id` 一列)
|
||||
- `StartIndex to EndIndex` 在选择列表里取列区间;`0 to 1` 返回第 0、1 两列
|
||||
|
||||
### 输出列表里的同名列会被覆盖
|
||||
|
||||
<!-- section-id: syntax-13-032 -->
|
||||
|
||||
<!-- tags: 同名列丢失, join 后值不对, 列被覆盖, 两个表同字段, 必须起别名 -->
|
||||
|
||||
`join` 两侧有同名字段又不改名时,靠后的列覆盖靠前的:
|
||||
|
||||
代码块身份:可直接照写示例
|
||||
|
||||
```tsl
|
||||
t1 := array(("A": 1, "B": 2, "C": 7),
|
||||
("A": 10, "B": 3, "C": 12),
|
||||
("A": 4, "B": 20, "C": 34));
|
||||
t2 := array(("A": 10, "B": 10, "D": 3),
|
||||
("A": 4, "B": 10, "D": 3));
|
||||
|
||||
dup_rows := select [1].*, [2].["B"], [2].["D"]
|
||||
from t1 join t2 on [1].["A"] = [2].["A"] end;
|
||||
writeLn("dup B:", dup_rows[0]["B"]);
|
||||
|
||||
alias_rows := select [1].*, [2].["B"] as "B2", [2].["D"]
|
||||
from t1 join t2 on [1].["A"] = [2].["A"] end;
|
||||
writeLn("kept B:", alias_rows[0]["B"]);
|
||||
writeLn("added B2:", alias_rows[0]["B2"]);
|
||||
```
|
||||
|
||||
结果说明:
|
||||
|
||||
- `dup B` 输出 `10`:`[1].*` 已带来左表的 `B`(值 `3`),后写的 `[2].["B"]` 把它覆盖成 `10`
|
||||
- 结果集里只有一列 `B`,左表原值无法再取回,且不会有任何报错
|
||||
- `kept B` 输出 `3`、`added B2` 输出 `10`:给右侧列写 `as "B2"` 后两列并存
|
||||
- 所以 `[表序号].*` 与显式列混写时,要先确认展开后有没有撞名
|
||||
|
||||
代码块身份:输出片段
|
||||
|
||||
```text
|
||||
dup B:10
|
||||
kept B:3
|
||||
added B2:10
|
||||
```
|
||||
|
||||
### `drange` 取行区间
|
||||
|
||||
<!-- section-id: syntax-13-021 -->
|
||||
@@ -1005,6 +1048,7 @@ query_result := select * from source_rows end;
|
||||
- 处理一维数组时直接把 `[0]` 当成稳定列访问。
|
||||
- 把 `thisGroup` 当成普通字段或普通变量。
|
||||
- 把排序后的 `thisRowIndex` 误当成排序序号。
|
||||
- 让 `[表序号].*` 和两侧同名的显式列同时出现在选择列表里,却不给其中一个写 `as` 别名。
|
||||
- 在 `left join` 时省略 `on` 子句或不用 `[表序号].["字段"]` 形式。
|
||||
- 在 `insert` 时漏掉 `insertfields` 或字段数与值数不匹配。
|
||||
- 期望 `update`/`delete` 返回新数组;它们直接修改原数组。
|
||||
|
||||
Reference in New Issue
Block a user