简单过一遍 Julia 中的流程控制。

条件语句

if 条件语句和其它语言一样,注意其中的条件表达式不需要括号

1
2
3
4
5
6
7
8
9
10
11
12
x = 3;
y = 2;

if x < y
println("x is less than y")
elseif x > y
println("x is greater than y")
else
println("x is equal to y")
end

# x is greater than y

C/C++ 使用 else if;Python 使用 elif;MATLAB 使用 elseif,Julia 也使用 elseif

需要注意的是,Julia 要求 ifelseif 所接受的条件必须是 Bool 值,不接受隐式转换,例如下面的语句是错误的

1
2
3
if 1    # error
println("1 is true")
end

还需要说明的是:和 Python 一样,Julia 在 if 语句中不会开辟独立的局部作用域。

Julia 支持三元运算符,可以用来简化判断语句,例如

1
2
3
4
x = 3;
y = 2;

m = x > y ? x : y # 3

Julia 还提供了一个内置函数 ifelse()

1
2
ifelse(1>0, 1, 0) # 1
ifelse(1<0, 1, 0) # 0

循环语句

while 循环语句也和其它语言一样

1
2
3
4
5
6
7
8
9
10
11
12
i = 0
while i <= 10
println(i)
i += 2
end

# 0
# 2
# 4
# 6
# 8
# 10

for 循环语句也和 MATLAB/Python 很类似,需要注意范围是闭区间而不是左闭右开,Julia 提供了三种等效的方式(=in),使用上没有区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
for i = 1:5
println(i)
end

# 1
# 2
# 3
# 4
# 5

for s in ["foo", "bar", "baz"]
println(s)
end

# foo
# bar
# baz

for s ∈ ["foo", "bar", "baz"]
println(s)
end

# foo
# bar
# baz

在循环中对于 breakcontinue 的支持也是类似的,无需重复。

有意思的是,Julia 支持将多重 for 循环写在一起,遍历笛卡尔积,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
for i = 1:3, j = 2:4
println((i, j))
end

# (1, 2)
# (1, 3)
# (1, 4)
# (2, 2)
# (2, 3)
# (2, 4)
# (3, 2)
# (3, 3)
# (3, 4)

在这种情况下,使用 break 语句会直接跳出整个循环。

需要注意,这里不能误写作 for i = 1:3; j = 2:4,因为会被视作复合表达式。

while 循环和 for 循环通常会引入变量局部作用域,这里暂时不作讨论。

复合表达式

有时我们只是希望将几个表达式按顺序组合到一起,依次运算,并使用最后一个表达式的值作为整体的结果,Julia 提供了 begin ... end 语法来完成这个功能,例如

1
2
3
4
5
6
x = begin
a = 1
b = 2
a + b
end
# x = 3

也可以写在一行中,此时表达式之间必须使用 ; 分隔

1
x = begin a = 1; b = 2; a + b end

可以使用 () 代替 begin ... end,此时表达式之间总是不能省略 ;

1
2
3
4
5
x = (a = 1;
b = 2;
a + b)

x = (a = 1; b = 2; a + b)

异常控制

抛出和捕获异常的语法和 Python,C++ 都差不多。

捕获异常

1
2
3
4
5
6
7
8
try
x = sqrt(-1)
println("result: $x")
catch e
println("exception:\n$e")
finally
println("finally")
end

输出形如

1
2
3
exception:
DomainError(-1.0, "sqrt was called with a negative real argument but will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).")
finally

主动抛出异常

1
2
3
f(x) = x>=0 ? exp(-x) : throw(DomainError("x<0"))

f(-1)

输出形如

1
2
3
4
5
6
7
ERROR: DomainError with x<0:

Stacktrace:
[1] f(x::Int64)
@ Main ./REPL[7]:1
[2] top-level scope
@ REPL[9]:1

补充

日志打印

Julia 内置了一些信息输出的工具,包括 @debug@info@warn@error,例如

1
2
3
4
5
6
7
8
9
10
11
12
julia> @debug("hi")

julia> @info("hi")
[ Info: hi

julia> @warn("hi")
┌ Warning: hi
└ @ Main REPL[12]:1

julia> @error("hi")
┌ Error: hi
└ @ Main REPL[13]:1

注意这里 @debug 的信息默认不会显示出来。

更完整的日志系统可以使用 Logging 这个包。