循环基本上分为两种类型:
这两种在 Julia 里都可以做到,不过第二种可能更常见。
while循环对于事先不知道要绕多少圈的开放式问题,Julia 提供了while循环。
基本形式相当简单:
while condition
do_something()
end
在这个例子里,程序会一直在循环里绕下去,直到condition不再是true。
有两种提前退出循环的办法:
break会让循环退出,程序从循环end之后的下一行继续执行。return x会停止当前函数的执行,把返回值x交回给调用方。有了这些选择,有时用while true ... end造一个“无限”循环会很方便,然后靠在循环体里找到停止条件来触发break或return。
最简单的例子是遍历一个范围。
如果我们想把某件事做 10 次:
for n in 1:10
do_something(n)
end
如果当前这次迭代不满足某个条件,可以用continue立刻跳到下一次迭代:
for n in 1:10
if is_useless(n)
continue
end
# we decided this iteration could be useful
do_something_slow(n)
end
写成更短的形式,if块可以换成is_useless(n) && continue。
许多其他类型的集合也可以遍历:数组里的元素、字符串里的字符、字典里的键……
要求是这个集合必须是iterable。
后面的某个概念会更详细地解释这一点,但本质上,集合必须能在被要求时给出下一项,并且能表示已经到达末尾、没有更多项了。
到目前为止的例子遍历的都是范围1:10,其中的值同时也是循环下标。
更一般地,需要的可能不只是值,还有下标。
这时要用eachindex()函数,例如for i in eachindex(my_array) ... end。
在 Julia 里,显式地写循环往往比在许多传统语言里更少见,因为有各种更简洁的写法。
一个特别常见的情形是,我们需要根据另一个集合(向量、字符串、集合……可能性很多)的元素构建一个新的向量。
喜欢 Python 列表推导式的人会很高兴地知道,Julia 可以使用类似的语法。
它的核心是在一个向量内部建立一个非常紧凑的循环。
最简单的语法形式是result = [f(x) for x in some_collection]。
用传统循环来写,可能是这样:
result = []
for x in some_collection
push!(result, f(x))
end
还可以在末尾加一个条件,只选出集合中符合条件的元素:
# multiples of 3
julia> [n^2 for n in 1:10 if n%3 == 0]
3-element Vector{Int64}:
9
36
81
# letters beyond 'h' in the alphabet
julia> [uppercase(c) for c in "Julia" if c > 'h']
3-element Vector{Char}:
'U': ASCII/Unicode U+0055 (category Lu: Letter, uppercase)
'L': ASCII/Unicode U+004C (category Lu: Letter, uppercase)
'I': ASCII/Unicode U+0049 (category Lu: Letter, uppercase)
这种语法和 Python 相似,但并不_完全相同_。 在多变量和/或多维数组上有一些差异,所以这个话题会在后面的概念里更详细地介绍。
作为一种现代的、以函数式为主的语言,Julia(当然)有多种操作集合的方式,不只是显式循环,也不只是推导式里那种压缩过的循环。
后面的概念会介绍一些替代方案,比如广播和高阶函数。