Skip to main content
Fluxon 的控制结构也是表达式:分支与循环可以产生值,并参与更大表达式的求值。本章覆盖 ifwhen、循环、break/continuetry

条件分支

基本语法

if 用于按条件选择不同的表达式结果:
if &n <= 1 then 1 else &n - 1
要点:
  • if 后跟条件表达式。
  • then 后跟条件为 true 时计算的表达式。
  • else 后跟条件为 false 时计算的表达式。
  • 整个 if ... then ... else ... 是一个表达式,可以直接作为函数返回值或赋值右侧:
def fib(n) = if &n <= 1 then 1 else fib(&n - 1) + fib(&n - 2)

多行与嵌套写法

当分支逻辑较复杂时,可以用代码块书写,并在 if 中嵌套使用:
result = if &score >= 90 {
	"A"
} else if &score >= 60 {
	"B"
} else {
	"C"
}
  • 花括号 { ... } 表示一个代码块。
  • 块内可以包含多条语句,块的结果是最后一个表达式的值,或者显式 return 的值。
  • if 是表达式,可以作为更大表达式的一部分,也可以嵌套出现在 else 分支中。

多分支选择

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

条件模式

在条件模式下,when 按顺序测试每个条件:
when {
	&num % 2 == 0 -> "even"
	&num < 0      -> "negative odd"
	else          -> "positive odd"
}
  • 花括号内部每一行是一个“条件 -> 结果表达式”。
  • 会自上而下依次计算条件表达式,返回第一个为 true 的分支右侧结果。
  • else 分支是可选分支,用于兜底情况。
  • 如果省略 else 且没有任何条件命中,则结果为 null
label = when {
	&status == "ok"    -> "OK"
	&status == "error" -> "ERROR"
}

值匹配

在值匹配模式下,when 先对一个表达式求值,然后与各个分支左侧的值做相等比较:
when &value {
	1    -> "one"
	2    -> "two"
	3    -> "three"
	else -> "other"
}
  • when expr { ... } 会先计算 expr,再依次与每个分支左侧的值比较。
  • 适合枚举值、常量分支、简单状态码等场景。
  • 同样支持 else 作为兜底分支。

与其他表达式组合

when 是表达式,可以绑定为变量、作为函数返回值,或嵌入到更大的表达式中:
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 提供 forwhile 两种循环形式,它们都可以在循环体中使用 breakcontinue

for-in 循环

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

遍历列表

sum = 0

for x in [1, 2, 3] {
	sum += &x
}
  • 语法为 for 标识符 in 可迭代表达式 { ... }
  • 在循环体中通过 &标识符 访问当前元素。
你也可以在循环中调用函数:
async def printAll(xs) = {
	for x in &xs {
		print(&x)
	}
}

遍历映射(键值对)

当可迭代值是键值对集合时,你可以直接解构当前项:
pairs = []

for (key, value) in &map {
	pairs += [&key + ":" + &value]
}
  • 使用解构 (key, value) 遍历键值对。
  • 具体迭代顺序由底层集合类型决定,例如字典或环境变量。

遍历区间

区间由 a..b(闭区间)或 a..<b(左闭右开)创建:
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
}
区间表达式本身是一个值,也可以先赋给变量再用于循环:
range = 1..10

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

while 循环

while 在条件为 true 时重复执行循环体:
count = 0
output = ""

while &count < 10 {
	count = &count + 1
	output = &output + &count + ","
}
  • 每次进入循环体之前都会计算条件表达式。
  • 条件结果为 falsenull 时循环结束。
  • 条件表达式可以引用外层变量,也可以调用函数:
def done(count) = &count >= 3

c = 0

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

终止与跳过

终止:break

break 用于提前结束当前循环:
status = "not-found"

for i in 1..10 {
	if &i == 5 {
		status = "found"
		break
	}
}
  • 立即结束最内层forwhile
  • 循环之后的语句会继续执行。
break 也可以配合 when 或函数调用使用,只要位置在循环体内即可。

跳过:continue

continue 用于跳过当前迭代剩余的语句,直接进入下一轮:
odds = []

for i in 1..10 {
	if &i % 2 == 0 {
		continue
	}
	odds += [&i]
}
  • 当前迭代中,continue 之后的语句不会执行。
  • 下一轮迭代从条件检查开始。
  • 在多重嵌套循环中,continue 只作用于最内层循环。

异常处理

Fluxon 提供 throwtry / catch / finally 结构来处理运行时错误。 和其他控制结构一样,try 是一个表达式,可以产生值。

抛出异常

使用 throw(expr) 可以在任意位置显式抛出异常:
throw("error")
在没有被 try 包裹时,throw 会中断当前脚本的执行,向外抛出一个运行时异常。 expr 的值会作为异常的消息或原因被传递到底层运行时:
def failIfNegative(n) = {
	if &n < 0 {
		throw("negative not allowed")
	}
	&n
}

作为表达式

try 是一个完整的表达式,用来包裹可能出错的代码,并在出错时给出替代值:
result = try {
	1 / 0
} catch (e) {
	"failed: " + &e.message
}
示例中的 &e.message 使用成员访问 .(反射)。嵌入式集成默认关闭反射访问,如需使用请参阅 成员访问(.)
求值规则概括如下:
  • 正常情况:
    • 先执行 try { ... } 块。
    • 如果没有抛出异常,try 表达式的结果就是 try 块最后一个表达式的值。
    • 如果存在 finally,仍然会在返回前执行 finally(见下文)。
  • 出错情况:
    • 如果 try 块中抛出了异常,会跳转到后续的 catch
    • 没有匹配的 catch 时,异常会继续向外传播。仅写 try { ... } 而不写 catch / finally 时,常用于“保证 finally 执行”或调试。
由于 try 是表达式,它可以出现在赋值、函数调用参数、甚至其他表达式内部:
status = try {
	parseConfig(&text)
} catch (e) {
	"invalid config: "
}

print("status = " + &status)

处理异常

catch 用于捕获异常并返回一个替代值。Fluxon 支持两种常见写法:
  1. 省略异常变量:只关心出错时的兜底结果,不关心异常对象本身:
    result = try {
    	throw("error")
    } catch {
    	"ok"
    }
    
  2. 带异常变量:需要访问异常对象的详细信息,例如类型或消息:
    result = try {
    	throw("error")
    } catch (e) {
    	"java.lang.RuntimeException: " + &e::message()
    }
    
在这两种形式中:
  • catch 块本身是一个代码块,最后一个表达式的值(或显式 return 的值)会成为整条 try 表达式在出错时的结果。
  • 如果 try 块没有抛出异常,对应的 catch 块不会执行。

最终执行

finally 用于那些不关心结果,只关心“必须执行”的逻辑,例如日志、资源释放或计时:
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 中,可以把多个异常处理片段写成一条链,形成紧凑的错误恢复逻辑:
result = try throw("error") catch "ok" finally print("done")
这与块体写法是等价的,只是把 trycatchfinally 部分写在一行上:
result = try {
	throw("error")
} catch {
	"ok"
} finally {
	print("done")
}
你可以根据脚本复杂度选择简写或块体形式:
  • 对于一两行的简单逻辑,简写更紧凑。
  • 涉及多步操作或需要访问异常对象时,推荐使用块体形式并显式写出 (e)

相关链接