循环语句通常用于遍历一个集合,或者重复执行若干指令,直到满足某个条件等等。 AviatorScript 支持 for
和 while
两种循环语句,分别介绍如下。
for 语句:遍历集合
for ... in
语句通常用于遍历一个集合,例如下面是遍历 0 到 9 的数字,并打印:
## examples/for_range1.av
for i in range(0, 10) {
println(i);
}
打印出:
0
1
2
3
4
5
6
7
8
9
其中 range(start, end)
函数用于创建一个 [start, end)
区间的整数集合,在迭代过程中,将 i
绑定到集合中的每个元素上,然后执行 {...}
里的代码块。大括号也是必需的,不能因为代码块是单行语句而忽略,这跟 java 是不同的。
range
函数还可以接受第三个参数,表示递增的 step 大小(不传默认 step 就是 1),比如我们可以打印 0 到 9 之间的偶数:
## examples/for_range2.av
for i in range(0, 10, 2) {
println(i);
}
打印:
0
2
4
6
8
for .. in
可以用于任何集合结构,比如数组、 java.util.List
、 java.util.Map
等等:
## examples/for_seq.av
let 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=1
b=2
c=3
sum of c is 45
关于 for 和集合 Sequence 的关系可以继续阅读第八章。
索引和 KV 遍历
从 5.2.4 版本开始, for
语句还支持迭代遍历过程带上索引或者 key/value:
## examples/for_index_kv.av
let 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] = 1
a[1] = 2
a[2] = 3
a[3] = 4
a[4] = 5
a[5] = 6
a[6] = 7
a[7] = 8
a[8] = 9
a = 1
b = 2
c = 3
null
continue/break/return
如果你想在执行代码块中途跳过剩余代码,继续下个迭代,可以用 continue
,比如下面的示例,跳过所有偶数,也就是打印奇数:
## examples/for_continue.av
for i in range(0, 10) {
if i % 2 == 0 {
continue;
}
println(i);
}
同样,如果想中途跳出迭代,你可以用 break:
## examples/for_break.av
for i in range(0, 10) {
if i > 5 {
break;
}
println(i);
}
当 i 大于 5 的时候,我们就跳出循环,因此只打印了:
0
1
2
3
4
5
return 有类似 break
的效果,也可以从循环中跳出,但是它会将整个脚本(或者函数)中断执行并返回,而不仅仅是跳出循环:
## examples/for_return.av
for 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.av
let sum = 1;
while sum < 1000 {
sum = sum + sum;
}
println(sum);
sum
从 1 开始,不停地累加自身,直到超过 1000 才终止,这里输出:
1024
while 后面跟 if 一样跟着一个布尔表达式,括号同样可以省略,但是代码块必须用大括号包围起来,这跟 if/for 也是一样的。
同样, while 也可以用 break 和 continue 语句,比如上面的例子我们可以改写成:
## examples/while2.av
let 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);