Sway 参考手册/循环
有时,程序员希望多次执行一段代码。这种任务通常使用循环来完成。Sway 中最基本的循环结构是 while 循环,其格式为...
whileloop: 'while' '(' expr ')' block
其中 expr 是任何解析为符号 :true 或 :false 的 Sway 表达式。
while 循环在执行循环主体之前测试其条件。如果初始测试失败,则主体根本不会执行。例如;
var i = 10; while (i < 10) { print(i); i = i + 1; }
不会打印任何内容,因为测试立即失败。在这个例子中,然而
var i = 0; while (i < 10) { print(i); i = i + 1; }
循环打印出数字 0 到 9
0123456789
while 循环重复执行其主体(循环的块部分)(只要条件保持为 true)。
要编写一个无限循环,请使用 :true 作为测试表达式
while (:true) { var i = getInput(); process(i); }
与 if 一样,所有 Sway 循环都是函数调用,通常带有近似块参数。如果需要,可以将小的近似块作为常规参数移到括号内。此外,if 的分号规则也适用于循环:循环本身具有近似块参数,后面不加分号。如果你要使用循环的返回值(对于 while,如果测试表达式最初为 true,则为 :true,如果测试表达式最初为 false,则为 :false),你需要在整个表达式后加上分号。
因为循环在 Sway 中很容易编写,所以只有 while 循环是内置的。其他循环可以在 "basics" 库中找到。要使用 "basics" 库,请添加函数调用
include("basics");
到源代码文件的最顶端。
do-until 循环类似于 while 循环,但循环的主体在进行测试之前执行一次。例如
var i = 10; do-until (i == 10) //note the test { print(i); i = i + 1; }
打印出 i 的值一次
10
请注意,do-until 在测试成功之前运行,这与 while 相反,while 在测试失败之前运行。
do-until 循环并不经常使用,尽管有时它对于处理交互式输入很有用。你总是可以将 do-until 编写为 while 循环。考虑这个循环
do-until (r == 0) { r = n / d; n = d; d = r; }
它可以被重写为一个 while 循环,如下...
finished = :false; while (!finished) { r = n / d; n = d; d = r; finished = (r == 0); }
请注意,变量 finished 被初始化为 :false,以确保循环主体至少进入一次。在循环底部,finished 被设置为 do-until 测试结果。
通常,do-until 更易于阅读和理解。
在许多程序中发现的另一个循环是 for 循环。for 循环由四个主要部分组成
- 初始化步骤
- 测试
- 主体
- 更新
请注意,这些组件与 while 循环完全对应
i = 0; // initialize while (i < MAX) // test { // body inspect(i); i = i + 1; // update (in body) }
其中更新通常是循环主体中的最后一条语句。相应的 for 循环为
for (i = 0, i < MAX, i = i + 1) // init, test, update { // body inspect(i); }
看看更新是如何从主体中移出的。
for 循环通常用于遍历数组中的每个元素
for (i = 0, i < length(items), i = i + 1) { a[i] = b[i] * c[i]; }
for 循环是一个计数循环。对于大多数(但并非全部)计数循环,循环变量(在本例中为 i)被初始化为零,循环测试(在本例中为i < length(items)) 被配置为只要循环变量严格小于计数的最大值就成功。如果循环主体要执行 n 次,则循环看起来像
for (i = 0, i < n, i = i + 1) { ... }
这种约定源于 Sway 中的数组(在后面的章节中详细介绍)使用 "基于零的索引"。也就是说,数组的第一个元素位于索引零处,第二个元素位于索引一处,依此类推。
除非有充分的理由,否则你应该始终使用这种约定[1]。
for-each 循环对于遍历数组和列表也很有用。它没有明确计数,但是
for-each (s,items) { inspect(s); }
在这个循环中,items 中的每个元素依次绑定到变量 s。循环主体执行的次数与数组或列表中的元素数量相同。请注意,与等效的 for 循环相比,for-each 循环要短得多
for (i = 0; i < length(item); i = i + 1) { var s = items[i]; inspect(s); }
它明确地计数。
除了循环条件或测试失败(或在 do-until 的情况下成功)之外,还有许多方法可以退出循环。即使在循环中间,也可以从函数中返回。这种技术经常用于搜索数组
function find(x,items) { var s; for-each(s,items) { if (x == s) { return :true; } } :false; }
请注意,如果未找到该项目,则循环最终会终止,并通过返回 :false 来表示失败。
你也可以通过调用 break 来退出循环,而无需完全退出函数
i = 0; while (i < 10) { if (i > 5) { break(); } inspect(i); } println(:done);
运行此代码将产生
i is 0 i is 1 i is 2 i is 3 i is 4 i is 5 done
你需要包含 basics 才能使用 break。你也可以简单地抛出一个类型为 :break 的异常
i = 0; while (i < 10) { if (i > 5) { throw(:break,0); } inspect(i); } println(:done);
最后,你可以通过使用 exit 函数来退出程序来退出循环
while (1) { var input = getInput(); if (reallyBad(input)) { exit(-1); //non-zero exit code } }
按照惯例,退出代码为零的 Sway 程序表示处理正常进行。非零退出代码表示发生某种致命错误。
- ↑ 相信我吧。