# 控制流
Deft 的控制流形式与裸函数调用自然地并列(参见
语法与风格)。本页涵盖条件分支、循环、
集合迭代,以及用于清理的 `defer`。
## `if` / `else`
### 单行形式(简单条件首选)
if ($n == 0) { return 1 } if logged-in? { set msg "Welcome!" } set msg [if admin? "Welcome, admin!" "Welcome, user!"]
### 多行形式(复杂逻辑)
if logged-in? { "Welcome!" } else { if admin? { "Welcome, admin!" } else { "Welcome, user!" } }
### 条件
条件是括号中的中缀表达式——或者裸的真值/假值。裸括号
`(...)` 不是函数调用(参见
语法与风格)。
if ($count > 10) { ... } # ✓ infix condition if logged-in? { ... } # ✓ bare predicate if $user~active { ... } # ✓ field access if [== $n 0] { ... } # ✗ invalid — `==` is infix-only, use ($n == 0)
### 真值性
`nil` 和 `false` 为假值。其他一切(包括 `0`、`""`、
`@{}`、`%{}`)都为真值。
if "" { echo "truthy" } # prints: truthy if 0 { echo "truthy" } # prints: truthy if nil { echo "nope" } # no output
## `match`
模式匹配在单个表达式中按形状、类型和内容进行分派。完整参考见
模式匹配。
def classify {|n^number| match $n { 0 => "zero" 1 .. 9 => "single digit" $x when ($x < 0) => "negative" _ => "positive" } }
## `for`——遍历集合
`for x in $xs { ... }` 迭代列表、映射、集合、字符串或任何
`ISeq`:
for x in @{ 1 2 3 } { echo $x } # 1 # 2 # 3 for entry in %{ :a 1 :b 2 } { echo "$entry(0) -> $entry(1)" # map yields @{key value} pairs } # a -> 1 # b -> 2 for ch in "abc" { echo $ch } # string yields single chars
### `break` 与 `continue`
for x in @{ 1 2 3 4 5 } { if ($x == 2) { continue } if ($x == 4) { break } echo $x } # 1 # 3
### 索引绑定
for x idx in $xs { echo "[$idx] $x" }
### 用于数值范围的 `range`
for i [range 0 10] { echo $i } # 0..9 for i [range 1 10 2] { echo $i } # 1 3 5 7 9
## `while`——带条件的循环
set n 0 while ($n < 5) { echo $n incr n }
`while` 最适合无界迭代(解析输入、轮询、退避)。集合迭代
优先使用 `for`。
## `each`——带副作用的遍历
`each` 是 `for` 的函数形式。在管道中使用它:
@{ 1 2 3 } |> each { echo $it }
%{ :a 1 :b 2 } |> each { echo "$it(0) = $it(1)" }
返回 `nil`。不要把它与 `map` 混淆(后者产生惰性序列)。
## `defer`——退出时清理
`defer` 调度一个代码块,在外层函数返回时运行,无论是正常返回
还是通过提前 `return`/抛出的错误返回。各 defer 按
后进先出顺序运行。
def with-file {|path^string| set fh [fs/open $path "r"] defer { fs/close $fh } # ... use $fh ... # fs/close runs when the function exits, however it exits. }
### LIFO 顺序
def ordered {| defer { echo "first" } defer { echo "second" } defer { echo "third" } "done" | } ordered # prints: third, second, first
### 提前返回时的执行
def parse-config {|path^string| set raw [unwrap [fs/read $path]] defer { echo "parsed $path" } # runs even on early return if (empty? $raw) { return %{} } [json/parse $raw] }
### 作用域独立性
嵌套 `def` 内的 `defer` 只在该嵌套函数返回时触发——defer 绑定到
函数帧,而非代码块:
def outer {| defer { echo "outer exits" } def inner {|| defer { echo "inner exits" } "inner" | } [inner] "outer" | } # inner exits # outer exits
另见并发,了解 `defer` 在异步资源方面的作用。
## `try` / `catch`——错误处理
try { set result [unwrap [fs/read $path]] [json/parse $result] } catch e { echo "failed: $e~message" %{} }
被捕获的值是一个带标签的 `%Err{ :message ... }` 映射。完整的 Result
机制(包括 `ok`/`err`/`?`/`unwrap`)见
错误处理。
## `throw`——显式错误
def divide {|a b| if ($b == 0) { [throw "division by zero"] } ($a / $b) }
抛出的值成为被 `try` 捕获的 `%Err{ :message ... }` 载荷。
## 提前 `return`
`return` 携带给定值立即退出外层函数:
def find-first-positive {|xs^list| for x in $xs { if ($x > 0) { return $x } } nil }
函数内闭包体中的 `return` 仍从外层函数返回,而不是从
闭包返回——闭包不引入新的返回帧。
## 快速参考
| 形式 | 用途 |
|---|---|
| `if cond { ... } else { ... }` | 条件分支 |
| `match expr { pattern => result ... }` | 基于形状的分派 |
| `for x in $xs { ... }` | 遍历集合 |
| `for x idx in $xs { ... }` | 带索引遍历 |
| `while cond { ... }` | 条件控制的循环 |
| `each` | 带副作用的函数式遍历(用于管道) |
| `defer { ... }` | 调度清理 |
| `try { ... } catch e { ... }` | 错误处理 |
| `return value` | 提前退出 |
| `break` / `continue` | 循环控制 |
| `[macro/compile-when cond body]` | 编译期条件——若 `cond` 为假则省略 `body`(参见宏) |