# for 循环

## 功能
`for` 用于重复执行代码、按整数区间循环、无限循环，也用于遍历数组、对象和字符串。

数组按下标和值遍历，对象按 key 和 value 遍历，字符串按字符遍历。整数次数和区间循环使用惰性迭代状态，不会提前生成完整数组。

## 语法
```bt
// 无限循环
for {
    statement
}

// 重复 count 次
for count {
    statement
}

// 重复 count 次，i 为下标
for i in count {
    statement
}

// 重复 count 次，i 从 0 开始按 step_value 递增
for i in count step step_value {
    statement
}

// 从 start 到 end，i 为下标
for i in start..end {
    statement
}

// 从 0 到 end，i 为下标
for i in ..end {
    statement
}

// 从 start 开始无限递增，i 为下标
for i in start.. {
    statement
}

// 正反向步长
for i in start..end step step_value {
    statement
}

// 遍历可迭代对象
for value in iterable {
    value
}

// 遍历对象
for key, value in iterable {
    value
}

// 逗号可省略
for key value in iterable {
    value
}

// _ 占位
for _, value in iterable {
    value
}

// 解构赋值
for (name, age) in iterable {
    name
}

// 标签循环，主要用于多 for 嵌套循环
for:label key, value in iterable {
    break:label
}
```

## 参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| count | Int | 是 | 循环次数，必须是非负整数。 |
| start | Int | 否 | 区间起点，省略时默认为 `0`。 |
| end | Int | 否 | 闭区间终点，省略时表示从 `start` 开始无限递增。 |
| step_value | Int | 否 | 正整数步长，默认 `1`；用于次数循环时控制当前值增量，用于区间循环时控制区间步幅。 |
| iterable | Array/Object/String/Int | 是 | 可遍历值；整数会按 `0..count - 1` 惰性循环。 |
| key | String/Int | 否 | 数组和字符串为下标，对象为 key，整数次数循环为当前整数，区间为零基序号。 |
| value | Any | 否 | 当前元素值；区间和整数次数循环中为当前整数。 |
| _ | Empty | 否 | 占位索引变量 |

## 返回值
`for` 语句本身返回 `empty`。如果需要收集结果，通常先创建数组或对象，在循环体内写入。

## 无限循环
`for {}` 表示无限循环，需要在循环体内通过 `break`、`return` 或 `exit` 退出。

```bt
i = 0
for {
    if i >= 3 {
        break
    }
    println i
    i += 1
}
```

## 重复 N 次
不需要索引时，直接写次数。

```bt
for 3 {
    println 'hello'
}
```

需要索引时，使用 `for i in count`。索引从 `0` 开始，到 `count - 1` 结束。

```bt
for i in 3 {
    println i
}
```

需要固定循环次数但让变量按指定步长递增时，使用 `for i in count step step_value`。下面会循环 3 次，输出 `0`、`2`、`4`。

```bt
for i in 3 step 2 {
    println i
}
```

## 区间循环
`start..end` 是闭区间，包含左右边界。起点小于等于终点时递增，起点大于终点时递减。

```bt
for i in 1..3 {
    println i
}

for i in 3..1 {
    println i
}
```

`..end` 等价于 `0..end`。

```bt
for i in ..3 {
    println i
}
```

`start..` 表示从起点开始无限递增。

```bt
for i in 100.. {
    if i > 102 {
        break
    }
    println i
}
```

## step
`step` 用于控制 `for` 循环中每次迭代的变量变动幅度（步长）。次数循环会固定执行 `count` 次，变量从 `0` 开始每轮增加 `step`；区间循环的方向由区间起始值与结束值的大小关系自动决定。

### 语法
`for <变量> in <次数> step <步长>`

`for <变量> in <区间> step <步长>`

## 约束条件

- `step` 必须为 **大于 `0` 的整数**
- 不支持负值步长（方向由区间自动决定）

## 行为规则

### 1. 默认步长

当省略 `step` 时，步长默认为 `1`。

### 2. 次数循环

`for i in count step step_value` 会执行 `count` 次，`i` 依次为 `0`、`step_value`、`step_value * 2`，直到达到执行次数，不会把 `count` 当作闭区间终点。

### 3. 方向自动判定

- **正向迭代**：当 `起始 ≤ 结束` 时，每次循环变量 **增加** `step`
- **反向迭代**：当 `起始 > 结束` 时，每次循环变量 **减少** `step`

### 4. 区间特性

- 区间为 **闭区间**：起始值和结束值均会被迭代（若步长能精确到达）
- 正向迭代终止条件：`变量 > 结束`
- 反向迭代终止条件：`变量 < 结束`

### 示例

| 代码 | 迭代序列 | 说明 |
|------|----------|------|
| `for i in 3 step 2` | 0, 2, 4 | 循环 3 次，当前值按 2 递增 |
| `for i in 0..6` | 0, 1, 2, 3, 4, 5, 6 | 默认步长 1，正向 |
| `for i in 0..6 step 2` | 0, 2, 4, 6 | 步长 2，正向 |
| `for i in 6..0` | 6, 5, 4, 3, 2, 1, 0 | 默认步长 1，反向 |
| `for i in 6..0 step 2` | 6, 4, 2, 0 | 步长 2，反向 |
| `for i in 1..10 step 3` | 1, 4, 7, 10 | 步长 3，正向 |
| `for i in 10..1 step 3` | 10, 7, 4, 1 | 步长 3，反向 |

```bt
for i in 3 step 2 {
    // 0, 2, 4
    println i
}

for i in 0..6 step 2 {
    // 0, 2, 4, 6
    println i
}

for i in 6..0 step 2 {
    // 6, 4, 2, 0
    println i
}
```

### 设计原理
`step` 仅定义每次迭代的变动幅度（步长绝对值）。区间循环的迭代方向完全由起始与结束的大小关系隐式决定，避免了显式指定 `-2` 这类负步长的冗余。

## 遍历集合
只关心元素本身时，写一个变量即可。

```bt
names = ['Lisa', 'Suci', 'Emerie']
for name in names {
    println name
}
```

需要下标或对象 key 时，写两个变量：第一个是 key，第二个是 value。两个变量之间的逗号可写可省略。

```bt
users = {name: 'Lisa', age: 18}
for key, value in users {
    println key + ': ' + string(value)
}

for key value in users {
    println key + ': ' + string(value)
}
```

## 丢弃绑定
`_` 表示丢弃当前绑定，不会创建或覆盖名为 `_` 的变量。

```bt
for _, value in users {
    println value
}

for key, _ in users {
    println key
}

for _, _ in users {
    println 'item'
}
```

## 解构当前 value
当遍历数组中的对象或数组时，可以在 `for` 后使用括号解构当前 value，只取循环体需要的字段。

```bt
users = [
    {name: '张三', age: 18}
    {name: '李四', age: 20}
]

for (name age) in users {
    println name + ':' + string(age)
}
```

上面的写法等价于：

```bt
for index, user in users {
    name = user.name
    age = user.age
    println name + ':' + string(age)
}
```

括号内可以使用空格或逗号分隔变量。当前 value 是 object 时按同名字段读取，是 array 时按下标读取；缺失字段或下标赋值为 `empty`。当前 value 不是 array 或 object 时会产生运行时错误。

## break 和 continue
`break` 立即结束当前循环；`continue` 跳过本次循环剩余语句，进入下一次循环。

```bt
for index, value in [1, 2, 3, 4] {
    if value == 2 {
        continue
    }
    if value == 4 {
        break
    }
    println value
}
```

## 标签循环
嵌套循环中，可以给循环加标签，然后用 `break:label` 或 `continue:label` 控制指定层级。冒号用于明确表示后面是跳转标签，标签写在循环关键字后面，格式为 `for:a`、`while:a` 或 `loop:a`。

```bt
arr = ['Lisa', 'Suci', 'Emerie']
list = ['Rita', 'maria', 'Jenna']

for:a k1, v1 in arr {
    for:b k2, v2 in list {
        if k1 == 1 {
            break:a
        }
        if k2 == 1 {
            continue:b
        }
        println v2
    }
    println v1
}
```

## 注意事项
- `for count {}` 的 count 必须是非负整数；`0` 会执行零次。
- `for i in count {}` 中的 count 为整数时，按 `0..count - 1` 循环；`for i in count step step_value {}` 会循环 count 次，i 从 `0` 开始按 step_value 递增。
- 区间循环只支持整数，第一版不支持浮点 step。
- `start..end` 包含 end。
- `start..` 是无限递增区间，通常需要在循环体内配合 `break`。
- `for value in obj` 仍然读取对象 value；需要对象 key 时使用 `for key, value in obj` 或 `for key value in obj`。
