@@ -13,9 +13,12 @@
|
||||
<!-- section-id: syntax-07-002 -->
|
||||
|
||||
- `if ... then ... else ...` 默认写成块式分支:`then begin ... end else begin ... end`。
|
||||
- 两个相邻的 `if ... then begin ... end` 是两条**独立**语句,两个条件都会求值、都可能执行;只有写了 `else` 才是互斥分支。
|
||||
- 块式分支内部的普通语句必须用分号结尾。
|
||||
- 控制流块的 `begin ... end` 后可以加分号也可以不加(语法都允许)。
|
||||
- `for` 支持 `to`、`downto`、可选 `step`,以及 `for i, v in array` 遍历。
|
||||
- `for ... in` 也可以只写一个控制变量:`for i in array do` 里的 `i` 是行下标/键,不是行值;要拿到行值就写两个控制变量。
|
||||
- 二维数组按 `for i, v in array` 遍历时按行推进,`v` 本身是整行数组;要落到单元格需要再嵌套一层 `for ... in`。
|
||||
- 计数 `for` 的初值、终值和步长确定后,循环次数随之固定;循环体内不要给控制变量赋值。
|
||||
- `for i, v in array` 遍历期间,不要修改被遍历数组或其中元素。
|
||||
- `while` 和 `repeat ... until` 都可直接使用;`repeat` 至少会先执行一轮再判断结束条件。
|
||||
@@ -77,6 +80,47 @@ writeLn(counter);
|
||||
0
|
||||
```
|
||||
|
||||
相邻两个 `if` 与 `if ... else` 的区别:
|
||||
|
||||
代码块身份:可直接照写示例
|
||||
|
||||
```tsl
|
||||
trace := "";
|
||||
if 1 then
|
||||
begin
|
||||
trace := trace + "A";
|
||||
end
|
||||
if 1 then
|
||||
begin
|
||||
trace := trace + "B";
|
||||
end
|
||||
writeLn(trace);
|
||||
|
||||
trace2 := "";
|
||||
if 1 then
|
||||
begin
|
||||
trace2 := trace2 + "A";
|
||||
end
|
||||
else
|
||||
begin
|
||||
trace2 := trace2 + "B";
|
||||
end
|
||||
writeLn(trace2);
|
||||
```
|
||||
|
||||
结果说明:
|
||||
|
||||
- 第一段输出 `AB`:两个 `if` 是两条独立语句,条件都为真所以都执行
|
||||
- 第二段输出 `A`:`if ... else` 是一条语句,两支互斥
|
||||
- 所以“多个条件里只能命中一个”必须写 `else`,靠相邻 `if` 排列不成立
|
||||
|
||||
代码块身份:输出片段
|
||||
|
||||
```text
|
||||
AB
|
||||
A
|
||||
```
|
||||
|
||||
### `for` 的几种主干写法
|
||||
|
||||
<!-- section-id: syntax-07-005 -->
|
||||
@@ -166,6 +210,73 @@ for i, value in numbers do
|
||||
230
|
||||
```
|
||||
|
||||
### `for ... in` 的控制变量个数
|
||||
|
||||
<!-- section-id: syntax-07-013 -->
|
||||
|
||||
<!-- tags: 遍历只写一个变量, 键还是值, 遍历二维数组, 每行是数组, 嵌套遍历 -->
|
||||
|
||||
一个控制变量拿到的是下标/键,两个才拿到行值:
|
||||
|
||||
代码块身份:可直接照写示例
|
||||
|
||||
```tsl
|
||||
data := array("a": 1, "b": 5, "c": 3, "d": -2);
|
||||
total := 0;
|
||||
for i, value in data do
|
||||
total := total + value;
|
||||
writeLn(total);
|
||||
|
||||
keys := "";
|
||||
for i in data do
|
||||
keys := keys + i;
|
||||
writeLn(keys);
|
||||
```
|
||||
|
||||
结果说明:
|
||||
|
||||
- 先输出 `7`:两个控制变量时,`value` 是行值
|
||||
- 再输出 `abcd`:只写一个控制变量时,它是行下标/键,不是行值
|
||||
- 所以想累加数值却只写一个控制变量,会拿到键而不是值
|
||||
|
||||
代码块身份:输出片段
|
||||
|
||||
```text
|
||||
7
|
||||
abcd
|
||||
```
|
||||
|
||||
二维数组按行推进,每个 `value` 本身是一行数组:
|
||||
|
||||
代码块身份:可直接照写示例
|
||||
|
||||
```tsl
|
||||
rows := array(("A": 1, "B": 2), ("A": 3, "B": 4));
|
||||
colA := 0;
|
||||
for i, value in rows do
|
||||
colA := colA + value["A"];
|
||||
writeLn(colA);
|
||||
|
||||
all := 0;
|
||||
for i, value in rows do
|
||||
for j, cell in value do
|
||||
all := all + cell;
|
||||
writeLn(all);
|
||||
```
|
||||
|
||||
结果说明:
|
||||
|
||||
- 先输出 `4`:`value` 是整行数组,可以直接按列键取 `value["A"]`
|
||||
- 再输出 `10`:要落到每个单元格,需要再嵌套一层 `for ... in`
|
||||
- 所以二维数组不会被自动摊平成单元格序列
|
||||
|
||||
代码块身份:输出片段
|
||||
|
||||
```text
|
||||
4
|
||||
10
|
||||
```
|
||||
|
||||
### `break` 与 `continue`
|
||||
|
||||
<!-- section-id: syntax-07-006 -->
|
||||
@@ -500,6 +611,9 @@ end
|
||||
- 把控制流问题和函数文件模型问题混在一起排查。
|
||||
- 在计数 `for` 循环体里给控制变量赋值。
|
||||
- 在 `for ... in` 遍历期间修改被遍历数组或其中元素。
|
||||
- 用相邻两个 `if ... then begin ... end` 表达互斥分支;它们是两条独立语句,需要互斥就写 `else`。
|
||||
- 在 `for ... in` 只写一个控制变量却当成行值使用;单变量拿到的是下标/键。
|
||||
- 以为二维数组会被 `for ... in` 摊平成单元格序列;它按行推进,行本身是数组。
|
||||
|
||||
代码块身份:反例 / 不可照写
|
||||
|
||||
|
||||
Reference in New Issue
Block a user