循环语句通常用于遍历一个集合,或者重复执行若干指令,直到满足某个条件等等。 AviatorScript 支持 for 和 while 两种循环语句,分别介绍如下。
for 语句:遍历集合
for ... in 语句通常用于遍历一个集合,例如下面是遍历 0 到 9 的数字,并打印:
## examples/for_range1.avfor i in range(0, 10) {println(i);}
打印出:
0123456789
其中 range(start, end) 函数用于创建一个 [start, end) 区间的整数集合,在迭代过程中,将 i 绑定到集合中的每个元素上,然后执行 {...} 里的代码块。大括号也是必需的,不能因为代码块是单行语句而忽略,这跟 java 是不同的。
range 函数还可以接受第三个参数,表示递增的 step 大小(不传默认 step 就是 1),比如我们可以打印 0 到 9 之间的偶数:
## examples/for_range2.avfor i in range(0, 10, 2) {println(i);}
打印:
02468
for .. in 可以用于任何集合结构,比如数组、 java.util.List 、 java.util.Map 等等:
## examples/for_seq.avlet m = seq.map("a", 1, "b", 2, "c", 3);for x in m {println(x.key + "=" + x.value);}let list = seq.list(1, 2, 3, 4, 5, 6, 7, 8, 9);let sum = 0;for x in list {sum = sum + x;}println("sum of list is "+ sum);
这里 m 是一个 HashMap ,通过 seq.map 函数创建,里面是三个键值对 a=1, b=2, c=3 ,我们也可以通过 for...in 语句来遍历,并且通过 x.key 和 x.value 来访问每一对的键值。
list 就是一个 1 到 9 整数组成的 List ,我们利用 for 语句迭代累计它们的和 sum 并打印。
最终输出:
a=1b=2c=3sum of c is 45
关于 for 和集合 Sequence 的关系可以继续阅读第八章。
索引和 KV 遍历
从 5.2.4 版本开始, for 语句还支持迭代遍历过程带上索引或者 key/value:
## examples/for_index_kv.avlet a = tuple(1, 2, 3, 4, 5, 6, 7, 8, 9);for i, x in a {assert(i + 1 == x);p("a[#{i}] = #{x}");}let m = seq.map("a", 1, "b", 2, "c", 3);for k, v in m {p("#{k} = #{v}");if k == "a" {assert(v == 1);}elsif k == 'b' {assert(v == 2);}elsif k == 'c' {assert(v == 3);}else {throw "should not happen";}}
通过 key[index], value 的形式就可以带上索引或者 KV 对(仅限 Map 类型)来遍历,输出:
a[0] = 1a[1] = 2a[2] = 3a[3] = 4a[4] = 5a[5] = 6a[6] = 7a[7] = 8a[8] = 9a = 1b = 2c = 3null
continue/break/return
如果你想在执行代码块中途跳过剩余代码,继续下个迭代,可以用 continue ,比如下面的示例,跳过所有偶数,也就是打印奇数:
## examples/for_continue.avfor i in range(0, 10) {if i % 2 == 0 {continue;}println(i);}
同样,如果想中途跳出迭代,你可以用 break:
## examples/for_break.avfor i in range(0, 10) {if i > 5 {break;}println(i);}
当 i 大于 5 的时候,我们就跳出循环,因此只打印了:
012345
return 有类似 break 的效果,也可以从循环中跳出,但是它会将整个脚本(或者函数)中断执行并返回,而不仅仅是跳出循环:
## examples/for_return.avfor i in range(0, 10) {if i > 5 {return;}println(i);}println("Can't reach here");
当 i 大于 5 的时候,我们就直接返回了, for 循环之后的代码也不会执行,因此也不会打印 Can't reach here 。
while 语句
while 循环本质上是条件语句和循环的结合,当满足一定条件下,不停地执行一段代码块,直到条件变为否定:
## examples/while1.avlet sum = 1;while sum < 1000 {sum = sum + sum;}println(sum);
sum 从 1 开始,不停地累加自身,直到超过 1000 才终止,这里输出:
1024
while 后面跟 if 一样跟着一个布尔表达式,括号同样可以省略,但是代码块必须用大括号包围起来,这跟 if/for 也是一样的。
同样, while 也可以用 break 和 continue 语句,比如上面的例子我们可以改写成:
## examples/while2.avlet sum = 1;while true {sum = sum + sum;if sum > 1000 {break;}}println(sum);
使用 while true 来无限循环,直到 sum 大于 1000 就 break 跳出。
return/continue 的使用和 for 类似,不再赘述。
循环语句也可以多层嵌套,这跟其他语言都没有什么两样:
let c = 0;for i in range(0, 10) {for j in range(0, 10) {c = c + i * j;}}println(c);
