> ## Documentation Index
> Fetch the complete documentation index at: https://fluxon.tabooproject.org/llms.txt
> Use this file to discover all available pages before exploring further.

# 控制流

> 分支、循环与异常处理等控制结构

Fluxon 的控制结构也是表达式：分支与循环可以产生值，并参与更大表达式的求值。本章覆盖 `if`、`when`、循环、`break/continue` 与
`try`。

## 条件分支

### 基本语法

`if` 用于按条件选择不同的表达式结果：

```fluxon theme={null}
if &n <= 1 then 1 else &n - 1
```

要点：

* `if` 后跟条件表达式。
* `then` 后跟条件为 `true` 时计算的表达式。
* `else` 后跟条件为 `false` 时计算的表达式。
* 整个 `if ... then ... else ...` 是一个表达式，可以直接作为函数返回值或赋值右侧：

```fluxon theme={null}
def fib(n) = if &n <= 1 then 1 else fib(&n - 1) + fib(&n - 2)
```

### 多行与嵌套写法

当分支逻辑较复杂时，可以用代码块书写，并在 `if` 中嵌套使用：

```fluxon theme={null}
result = if &score >= 90 {
	"A"
} else if &score >= 60 {
	"B"
} else {
	"C"
}
```

* 花括号 `{ ... }` 表示一个代码块。
* 块内可以包含多条语句，块的结果是最后一个表达式的值，或者显式 `return` 的值。
* `if` 是表达式，可以作为更大表达式的一部分，也可以嵌套出现在 `else` 分支中。

## 多分支选择

`when` 提供了更灵活的多分支选择语法，支持按条件测试和按值匹配两种用法。

### 条件模式

在条件模式下，`when` 按顺序测试每个条件：

```fluxon theme={null}
when {
	&num % 2 == 0 -> "even"
	&num < 0      -> "negative odd"
	else          -> "positive odd"
}
```

* 花括号内部每一行是一个“条件 -> 结果表达式”。
* 会自上而下依次计算条件表达式，返回第一个为 `true` 的分支右侧结果。
* `else` 分支是可选分支，用于兜底情况。
* 如果省略 `else` 且没有任何条件命中，则结果为 `null`：

```fluxon theme={null}
label = when {
	&status == "ok"    -> "OK"
	&status == "error" -> "ERROR"
}
```

### 值匹配

在值匹配模式下，`when` 先对一个表达式求值，然后与各个分支左侧的值做相等比较：

```fluxon theme={null}
when &value {
	1    -> "one"
	2    -> "two"
	3    -> "three"
	else -> "other"
}
```

* `when expr { ... }` 会先计算 `expr`，再依次与每个分支左侧的值比较。
* 适合枚举值、常量分支、简单状态码等场景。
* 同样支持 `else` 作为兜底分支。

### 集合匹配

`when` 支持使用 `in` 和 `!in` 检查值是否在集合、映射或区间内：

```fluxon theme={null}
when &score {
	in 0..59    -> "不及格"
	in 60..79   -> "及格"
	in 80..100  -> "优秀"
	else        -> "无效分数"
}
```

* `in <collection>` 检查主题值是否在集合中
* `!in <collection>` 检查主题值是否不在集合中
* 支持列表、映射、区间等可迭代值

### 类型匹配

`when` 支持使用 `is` 运算符进行类型检查：

```fluxon theme={null}
when &obj {
	is string -> "这是文本"
	is int    -> "这是整数"
	is list   -> "这是列表"
	else      -> "未知类型"
}
```

**类型匹配特性：**

* 使用 `is <TypeName>` 进行运行时类型检查
* 支持类型别名（不区分大小写）：`string`、`int`、`list`、`map` 等
* 支持完全限定类名：`is java.util.ArrayList`
* `null` 值不匹配任何类型，会进入 `else` 分支
* 可与其他匹配类型混合使用：

```fluxon theme={null}
when &value {
	null       -> "空值"
	is string  -> "文本类型"
	42         -> "答案"
	in 0..100  -> "数字范围"
	else       -> "其他"
}
```

详见 [运算符与优先级 - 类型检查](/language/operators-and-priority#类型检查运算符-is)。

### 与其他表达式组合

`when` 是表达式，可以绑定为变量、作为函数返回值，或嵌入到更大的表达式中：

```fluxon theme={null}
label = when &status {
	"ok"      -> "OK"
	"failed"  -> "FAILED"
	else      -> "UNKNOWN"
}

async def handleStatus(status) = {
	message = when &status {
		"ok"     -> "success"
		"queued" -> "pending"
		else     -> "error"
	}
	print(&message)
}
```

## 循环

Fluxon 提供 `for` 和 `while` 两种循环形式，它们都可以在循环体中使用 `break` 和 `continue`。

### for-in 循环

`for` 用于遍历列表、区间或映射等可迭代值。

#### 遍历列表

```fluxon highlight={3} theme={null}
sum = 0

for x in [1, 2, 3] {
	sum += &x
}
```

* 语法为 `for 标识符 in 可迭代表达式 { ... }`。
* 在循环体中通过 `&标识符` 访问当前元素。

你也可以在循环中调用函数：

```fluxon highlight={2} theme={null}
async def printAll(xs) = {
	for x in &xs {
		print(&x)
	}
}
```

#### 遍历映射（键值对）

当可迭代值是键值对集合时，你可以直接解构当前项：

```fluxon highlight={3} theme={null}
pairs = []

for (key, value) in &map {
	pairs += [&key + ":" + &value]
}
```

* 使用解构 `(key, value)` 遍历键值对。
* 具体迭代顺序由底层集合类型决定，例如字典或环境变量。

#### 遍历区间

区间由 `a..b`（闭区间）或 `a..<b`（左闭右开）创建：

```fluxon highlight={3,7} theme={null}
total = 0

for i in 1..5 {
	total += &i      # i = 1, 2, 3, 4, 5
}

for j in 0..<3 {
	print(&j)          # j = 0, 1, 2
}
```

区间表达式本身是一个值，也可以先赋给变量再用于循环：

```fluxon highlight={3} theme={null}
range = 1..10

for i in &range {
	print(&i)
}
```

### while 循环

`while` 在条件为 `true` 时重复执行循环体：

```fluxon highlight={4} theme={null}
count = 0
output = ""

while &count < 10 {
	count = &count + 1
	output = &output + &count + ","
}
```

* 每次进入循环体之前都会计算条件表达式。
* 条件结果为 `false` 或 `null` 时循环结束。
* 条件表达式可以引用外层变量，也可以调用函数：

```fluxon theme={null}
def done(count) = &count >= 3

c = 0

while !done(&c) {
	c = &c + 1
}
```

## 终止与跳过

### 终止：break

`break` 用于提前结束当前循环：

```fluxon highlight={5} theme={null}
status = "not-found"

for i in 1..10 {
	if &i == 5 {
		status = "found"
		break
	}
}
```

* 立即结束**最内层**的 `for` 或 `while`。
* 循环之后的语句会继续执行。

`break` 也可以配合 `when` 或函数调用使用，只要位置在循环体内即可。

```fluxon highlight={5-7} theme={null}
result = ""

for item in [1, 2, 3, "stop", 4, 5] {
	when &item {
		is string -> {
			result = "stopped at: " + &item
			break
		}
		else -> result = &result + &item + ","
	}
}
# result = "stopped at: stop"
```

### 跳过：continue

`continue` 用于跳过当前迭代剩余的语句，直接进入下一轮：

```fluxon highlight={5} theme={null}
odds = []

for i in 1..10 {
	if &i % 2 == 0 {
		continue
	}
	odds += [&i]
}
```

* 当前迭代中，`continue` 之后的语句不会执行。
* 下一轮迭代从条件检查开始。
* 在多重嵌套循环中，`continue` 只作用于最内层循环。

## 异常处理

Fluxon 提供 `throw` 与 `try` / `catch` / `finally` 结构来处理运行时错误。

和其他控制结构一样，`try` 是一个表达式，可以产生值。

### 抛出异常

使用 `throw(expr)` 可以在任意位置显式抛出异常：

```fluxon theme={null}
throw("error")
```

在没有被 `try` 包裹时，`throw` 会中断当前脚本的执行，向外抛出一个运行时异常。

`expr` 的值会作为异常的消息或原因被传递到底层运行时：

```fluxon highlight={3} theme={null}
def failIfNegative(n) = {
	if &n < 0 {
		throw("negative not allowed")
	}
	&n
}
```

### 作为表达式

`try` 是一个完整的表达式，用来包裹可能出错的代码，并在出错时给出替代值：

```fluxon theme={null}
result = try {
	1 / 0
} catch (e) {
	"failed: " + &e.message
}
```

<Note>示例中的 `&e.message` 使用成员访问 `.`（反射）。嵌入式集成默认关闭反射访问，如需使用请参阅 [成员访问（.）](/language/member-access)。</Note>

求值规则概括如下：

* 正常情况：
  * 先执行 `try { ... }` 块。
  * 如果没有抛出异常，`try` 表达式的结果就是 `try` 块最后一个表达式的值。
  * 如果存在 `finally`，仍然会在返回前执行 `finally`（见下文）。
* 出错情况：
  * 如果 `try` 块中抛出了异常，会跳转到后续的 `catch`。
  * 没有匹配的 `catch` 时，异常会继续向外传播。仅写 `try { ... }` 而不写 `catch` / `finally` 时，常用于“保证 finally 执行”或调试。

由于 `try` 是表达式，它可以出现在赋值、函数调用参数、甚至其他表达式内部：

```fluxon highlight={3} theme={null}
status = try {
	parseConfig(&text)
} catch (e) {
	"invalid config: "
}

print("status = " + &status)
```

### 处理异常

`catch` 用于捕获异常并返回一个替代值。Fluxon 支持两种常见写法：

1. **省略异常变量**：只关心出错时的兜底结果，不关心异常对象本身：

   ```fluxon highlight={3} theme={null}
   result = try {
   	throw("error")
   } catch {
   	"ok"
   }
   ```

2. **带异常变量**：需要访问异常对象的详细信息，例如类型或消息：

   ```fluxon highlight={3} theme={null}
   result = try {
   	throw("error")
   } catch (e) {
   	"java.lang.RuntimeException: " + &e::message()
   }
   ```

在这两种形式中：

* `catch` 块本身是一个代码块，最后一个表达式的值（或显式 `return` 的值）会成为整条 `try` 表达式在出错时的结果。
* 如果 `try` 块没有抛出异常，对应的 `catch` 块不会执行。

### 最终执行

`finally` 用于那些不关心结果，只关心“必须执行”的逻辑，例如日志、资源释放或计时：

```fluxon highlight={5} theme={null}
value = try {
	parseInt(&text)
} catch (e) {
	0
} finally {
	print("parse done")
}
```

执行顺序为：

1. 执行 `try` 块。
2. 若发生异常，执行 `catch` 块；`catch` 的返回值作为候选结果。
3. 不论是否发生异常，都执行 `finally` 块。
4. 如果 `finally` 正常结束，则 `try` 表达式的结果为：
   * 正常情况下：`try` 块的结果。
   * 出错且被捕获的情况下：`catch` 块的结果。

只有在 `finally` 内部再次抛出异常时，才会覆盖原本的结果，改为向外抛出新的异常。

否则，`finally` 不会改变 `try` / `catch` 已经决定好的值。

### 链式用法与简写形式

在 Fluxon 中，可以把多个异常处理片段写成一条链，形成紧凑的错误恢复逻辑：

```fluxon theme={null}
result = try throw("error") catch "ok" finally print("done")
```

这与块体写法是等价的，只是把 `try`、`catch`、`finally` 部分写在一行上：

```fluxon highlight={5} theme={null}
result = try {
	throw("error")
} catch {
	"ok"
} finally {
	print("done")
}
```

你可以根据脚本复杂度选择简写或块体形式：

* 对于一两行的简单逻辑，简写更紧凑。
* 涉及多步操作或需要访问异常对象时，推荐使用块体形式并显式写出 `(e)`。

## 相关链接

* [字面量与类型](/language/literals-and-types)
* [变量与引用](/language/variables-and-references)
* [运算符与优先级](/language/operators-and-priority)
* [成员访问（.）](/language/member-access)
* [函数与异步](/language/functions-and-async)
