julia:使用控制流程(learning julia)(完结)

本文深入探讨了Julia语言中的控制流概念,包括条件和循环结构的应用,异常处理的最佳实践,以及如何使用任务实现代码的协同执行。通过丰富的示例代码,读者可以更好地掌握Julia语言的流程控制特性。

与任何其他语言一样,Julia提供了控制代码流的功能。 控制流技术大部分遵循熟悉的模式; 然而,其中一些有微妙的变化。

在本章中,我们将详细解释如何使用各种控制流技术构建Julia程序,以提供有效的代码执行。 以下是我们将在本章中介绍的主题列表:

  • 有条件的和重复的评估
  • 异常处理
  • julia的任务

有条件的和重复的评估

条件评估有助于将代码分解为更小的块,每个块根据特定条件进行评估。 有许多方法可以强加这些条件,并且可以相应地处理代码。

我们将引导您完成各种条件代码评估方法。 但在我们走得更远之前,我们需要熟悉复合表达式。

复合表达式是我们确保以有序方式评估一系列代码的方式。 我们来看看一些代码:

julia> volume = begin
len = 10
breadth = 20
height = 30
len * breadth * height
end
6000
julia> volume
6000

在这里,我们有一个以复合表达式形式实现的简单逻辑。 如您所见,卷被计算为所有三个维度的乘积,然后分配回变量本身。 遵循的语法是begin … end。 但是,如果使用替代方法使用“;”声明复合表达式,则不必包含begin关键字, 这在以下示例中显示:

# Correct method of using ";" key
julia> volume = (length = 10; breadth = 20; height = 30; length * breadth *
height)
julia> volume
6000
# Wrong method of using ";" key
julia> volume = length = 10; breadth = 20; height = 30; length * breadth *
height
julia> volume
10

然而,重要的是要记住,在使用“;”时我们应该包括“(”和“)”(作为开始和结束括号)。 因为这可能最终分配错误的结果,如前面的代码所示(卷被分配给length的值)。 分号具有所有其他运算符的最低优先级。

有条件的评估详细

在编写任何代码时,我们经常遇到需要根据一组规则或预定义的业务逻辑做出某些决策的情况。 在这种情况下,我们通常希望代码足够智能,以便相应地采用正确的路径。 这是条件评估进入图片的时候。

我们来看看FizzBuzz的例子。 在这里,我们将实施着名的FizzBuzz程序,该程序指出,对于任何给定的数字范围(比如说1到30),打印Fuzz而不是3的倍数和Buzz的数字为5的倍数。对于同时存在的数字 可以被3和5整除,程序应该打印FizzBuzz。

julia> for i in 1:30
if i % 3 == 0 && i % 5 == 0
println("FizzBuzz")
elseif i % 3 == 0
println("Fizz")
elseif i % 5 == 0
println("Buzz")
else
println(i)
end
end
1 2
Fizz
4
Buzz
Fizz
7 8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz

因此,正如预期的那样,FizzBuzz字符串在第15和第30位打印两次,Fizz字符串打印八次,Buzz字符串打印四次。

该代码还包含一些未知的关键字,例如for和in,我们将在本章后面详细讨论。 但是,关键字if,elseif和else化妆我们统称为条件。

这种结构几乎存在于现代时代的每种编程语言中,只是使用end作为任何功能条件代码块的逻辑结尾的细微差别。

关键字if,else和elseif基本上用布尔术语来计算表达式。 因此,给定任何条件,if将尝试检查该表达式是否计算为true或false。 如果条件为布尔值true,那么if块中的代码将被评估; 否则,我们有一个else或elseif块。

但是,对程序中可能使用的else或elseif块的数量没有限制(正如我们在前面讨论的FizzBuzz算法编码解决方案中已经看到的那样)。

让我们再看一个例子,这次使用函数:

#Check whether a number is prime or not!
julia> function factors(num)
factors = []
for i in 1:num
if rem(num, i) == 0
push!(factors, i)
end
end
return factors
end
# Main logic
julia> function is_prime(num)
factors_array = factors(num)
if length(factors_array) == 2

return true
else
return false
end
end
julia> is_prime(10)
false
julia> is_prime(11)
true

所以,正如你必须注意到的那样,我们在函数因子中使用if块来获取任何数字的因子。 最值得注意的是if块不一定跟着else块! 另一方面,我们有is_prime函数,它使用if … else块来返回Boolean true或false值。
回到if块的使用,我们对来自其他编程语言的读者有一些惊喜:

  • if块漏了! 这意味着仍然可以使用if块内的变量,即使之前没有引入过。 正如官方Julia文档中所提到的,如果块没有引入本地范围:
julia> function f(n)
if n % 2 == 0
parity = "even"
else
parity = "odd"
end
println("The number is $parity")
end
f (generic function with 1 method)
julia> f(2)
The number is even
julia> f(1)
The number is odd
  • if块返回一个值! 对于来自不同语言的人来说,这是一个惊喜元素,尽管这是一个非常有用的功能:
# if statements return values
julia> x = if true
2
end
2
julia> x
2
# println is a Void function
julia> x = if true
println("test")
end
test
julia> x
julia> x == nothing
true
julia> nothing == println("test")
test
true

如果结果不是true或false,则if块将无法计算表达式。 例如,如果我们写这个:

julia> if 1
println(true)
end
ERROR: TypeError: non-boolean (Int64) used in boolean context

上面的代码会立即抛出一个错误,说它无法计算返回非布尔结果的表达式。 因此,对于来自Python等语言的人来说,写1(如果1)可能是可以的; 它不是Julia的有效操作。

在仔细研究了if-elseif-else块之后,让我们现在关注另一种称为三元运算符的条件表达式。 它们的工作方式几乎与块一样,但语法编写方式不同,操作符只能在单个表达式上运行!

三元运算符的语法可以总结如下:

condition ? do this, if true : do this, if false

让我们看一个使用相同语法的示例:

julia> name = "Julia"
"Julia"
julia> isa(name, String) ? "Its a string" : "Not a string"
"Its a string"
julia> name = 'j'
'j'
julia> isa(name, String) ? "Its a string" : "Not a string"
"Not a string

一开始,我们将name定义为等于Julia。 使用三元运算符语法和isa()函数,我们检查给定的名称是否是String类型。 正如预期的那样,对于第一次调用,它打印第一个条件,因为变量名是String类型,而在后一种情况下,变量名等于j,这是一个字符类型,因此使条件为false。

短路评估

在Julia中,除了常规的布尔运算符,例如true和false,我们还有&&和||。

他们背后的想法很简单:

  • 查看var1 && var2表达式,如果var1的计算结果为true,则仅执行var2
  • 看看var1 || 如果var1的计算结果为false,则仅对var2表达式进行求值
  • -
julia> isdigit("10") && println("Reached me!")
Reached me!
julia> isdigit("Ten") && println("Reached me!")
false
julia> isdigit("Ten") || println("Reached me!")
Reached me!

在第一行代码中,isdigit(“10”)函数接受一个字符串值并检查它是否为数字。 在这种情况下,当值为true时,第二个表达式println(“Reached me!”)已成功执行。

另一方面,在第三行代码中,isdigit(“Ten”)表达式求值为false,因此执行println(“Reached me!”)表达式。

反复评估

在仔细研究了条件评估在Julia中如何运作之后,让我们将重点转移到一个更重要的主题,即重复评估。

在Julia中,我们提供了两个结构,即while和for。 这两个用于评估循环中的代码。 以下是while和for循环的示例:

julia> collection = [1,2,3,4,5,6,7,8,9]
9-element Array{Int64,1}:
1
2
3
4
5
6
7
8
9
julia> while length(collection) > 1
pop!(collection)
println(collection)
end
[1,2,3,4,5,6,7,8]
[1,2,3,4,5,6,7]
[1,2,3,4,5,6]
[1,2,3,4,5]
[1,2,3,4]
[1,2,3]
[1,2]
[1]

在这个例子中,我们有一个从1到9的整数数组。我们将它命名为集合,然后我们使用while结构循环遍历项目数组,直到集合的长度大于1.但是,使用while编写的代码 如果没有正确提到我们的结束条件,循环很容易变成无限循环。 例如,在上面的代码中,我们使用了Julia提供的一个名为pop!的函数,它接收一个项目集合并从中删除(或弹出)最后一项,这样就可以将原始集合修改为更短更短。

如果我们没有控制while循环的终点,那就是它会产生的结果:

julia> collection = [1,2,3,4,5,6,7,8,9]
9-element Array{Int64,1}:
1
2
3
4
5
6
7
8
9
julia> while length(collection) > 1
println(collection)
end
[1,2,3,4,5,6,7,8]
[1,2,3,4,5,6,7,8]
[1,2,3,4,5,6,7,8]
[1,2,3,4,5,6,7,8]
[1,2,3,4,5,6,7,8]
[1,2,3,4,5,6,7,8]
[1,2,3,4,5,6,7,8]
....
. .

我们最终必须手动中断程序才能停止循环。 所以必须记住,在使用while循环之前,我们必须非常确定我们必须达到一个终点。

仔细观察之后,让我们继续讨论另一个名为for构造的构造。 它以下列方式工作:

julia> statement = "This is a great example!"
"This is a great example!"
julia> for words in split(statement)
println(words)
end
This
is
a
great
example!

正如您所看到的,对于类似的工作,通过循环遍历集合的每个项目,它将获得并执行所需的操作。 split()函数使用给定字符将字符串拆分为多个部分。 默认情况下,使用空格(“”)字符。

# using the value of statement from the above example
julia> split(statement)
5-element Array{SubString{String},1}:
"This"
"is"
"a"
"great"
"example!"

如果我们没有使用split(),这就是我们应该得到的:

julia> statement = "This is a great example!"
"This is a great example!"
julia> for words in statement
println(words)
end
T h i s i s a g r e a t e x a m p l e !

这有效地展示了差异。 在循环项目时想到的一个重要方面是我们如何控制要循环的对象范围。 这应该非常熟悉来自Python背景的人,因为它类似于Python中使用的切片技术。

再次,仔细看一个例子,我们可以操作字符串集合,如下所示:

julia> statement = "Yet another awesome example!"
"Yet another awesome example!"
julia> for word in split(statement)[2:4]
println(word)
end
another
awesome
example!
julia> for word in split(statement)[2:3:2]
println(word)
end
another

专注于split(语句)[2:4]代码,我们可以将其分解为两部分:split(语句)代码的第一部分拆分String类型值并将其转换为数组,[“Yet”,”another”,”awesome”,”example!”]; 而代码的第二部分在这个结果数组上运行,并从[2:4]循环,即第二个元素到第四个元素,导致“`[“another”,”awesome”,”example!”]值。

关于Julia不要忘记的重要一点是,数组的索引始终从1开始! 这与许多其他语言不同,其中起始索引为0。

定义范围

在编码时,我们经常遇到与要循环的项目范围有关的代码。 例如,有人知道1到10之间的数字是偶数还是奇数? 这很简单,但我们如何开始?

以下代码显示了我们可以轻松地执行此操作:

julia> numbers = [1,2,3,4,5,6,7,8,9,10]
10-element Array{Int64,1}:
1
2
3
4
5
6
7
8
9
10
julia> for n in numbers
if rem(n,2) == 0
println("$n is even")
end
end
2 is even
4 is even
6 is even
8 is even
10 is even

简单! 但等等 - 如果我们有100个号码怎么办? 我们会先创建一个包含100个数字的数组吗? 不,我们将使用范围表达式。 让我们看看实际情况:

julia> for n in 1:10
if rem(n,2) == 0
println("$n is even")
end
end
2 is even
4 is even
6 is even
8 is even
10 is even

优雅,不是吗? 重点关注我们如何使用1:10来定义从1到10开始的数字范围。它易于使用,并且只需要在给定的数字范围内循环就可以派上用场。

for循环的更多示例

试想一下,我们都被赋予了任务来创建模式。 这很简单,但它利用了迄今为止所获得的关于for构造的所有知识。

  • 直角三角形:一个非常简单的循环练习,涉及模仿直角三角形的尺寸:
julia> for i in 1:5
for j in 1:i
print("*")
end
println("")
end
*
**
***
****
*****

请注意我们如何仔细使用print()和println()函数。 区别在于打印不会改变行,而println将耗尽完整的行。

  • 倒三角形:这仅仅是一个示例中的初始三角形的反向:
julia> for i in 5:-1:1
for j in 1:i
print("*")
end
println("")
end
*****
****
***
**
*

关注我们如何使用5:-1:1来反转数字范围。 我们应该进一步尝试快速换弦吗? 为什么不!

  • 反转字符串:使用Julia中的切片技术来反转给定的字符串。 语法相当简单,与Python非常相似:
julia> my_string = "This is a great thing to do!"
julia> my_string[length(my_string):-1:1]
"!od ot gniht taerg a si sihT"

在这里,我们使用字符串的长度来指示要反转的元素的数量。 -1号实际上告诉Julia从结尾开始读取/解析字符串。

break 和continue

到目前为止,我们已经阅读并试验了很多关于for和while结构的内容。 然而,由于也被许多不同的语言提供,我们continue和break语句。

当我们希望将控件转移到外部代码块时,使用中断块。 这意味着我们不想进一步进行计算,并希望立即突破并从该循环周期中退出。 要理解这一点,让我们看一下以下示例:

julia> word = "julia"
"julia"
julia> for letter in word
println(letter)
if letter == 'l'
break
end
end
j u l

在这里,我们有一个带有“julia”值的词。 我们想要一个解决方案,一旦遇到名称中的l字母,就会出现for循环。 这是休息开始行动的地方,并且一旦条件满足就能够切断或脱离循环。

如果满足给定条件,则continue语句用于我们希望继续进行计算的位置。 以下是代码,经过修改以展示continue块的操作:

julia> for letter in "julia"
if letter == 'l'
continue
end
println(letter)
end
j u i a

异常处理

在编写任何代码时,如果出现问题我们该怎么办? 一个可能的答案是一次性编写完全正确的代码,但这在现实世界中并不常见。 很多时候,开发人员最终花费大量时间搞清楚错误,然后在代码中修复错误。 但是,不能处理无法处理预期(或意外)错误的情况的代码不能被认为是好代码!

建立适当的异常或错误处理很重要。 这可以通过使用Julia的内置异常处理方法来确保,我们将在这部分讨论
这一章。

让我们首先看看错误和异常之间的基本区别:

julia> println('hello world!')
ERROR: syntax: invalid character literal
# To get the following, press CTRL+C during the execution of the loop.
julia> for i in 1:100
println(i)
end
1 2 3 4
ERROR: InterruptException:
in process_events(::Bool) at ./libuv.jl:84
in wait() at ./event.jl:188
in stream_wait(::Task) at ./stream.jl:44
in uv_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:820
in unsafe_write(::Base.TTY, ::Ptr{UInt8}, ::UInt64) at ./stream.jl:830
in unsafe_write(::Base.TTY, ::Base.RefValue{UInt8}, ::Int64) at
./io.jl:155
in write(::Base.TTY, ::Char) at ./io.jl:194
in print(::Base.TTY, ::Char) at ./char.jl:45
in print(::Base.TTY, ::Char) at
/Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib:?
in print(::Base.TTY, ::Int128, ::Char, ::Vararg{Char,N}) at
./strings/io.jl:19
in macro expansion; at ./REPL[5]:2 [inlined]
in anonymous at ./<missing>:?

错误是指示问题的一个问题,应该避免,因此代码不应该捕获它。 通过捕获,我们的意思是说它不应该期待它。 另一方面,异常是代码可能期望的,并且可能存在开发人员想要捕获异常的条件。

Julia提供了许多类型的错误:

  • ArgumentError:传递给函数的参数与函数最初期望的参数不相似。
  • AssertionError:这是在写入错误的断言语句并且计算结果为false时的结果。
  • BoundsError:在索引数组时尝试访问越界元素。
  • DivideError:这是数字除以0时的结果。
  • DomainError:有效域之外的参数。
  • EOFError:这意味着您已到达文件的末尾,因此无需再从中读取任何内容。
  • InexactError:尝试进行精确类型转换失败。
  • KeyError:尝试访问不是关键元素的元素 - 也就是说,不存在。
  • LoadError:加载文件时发生错误。
  • MethodError:尝试使用不受支持的函数的签名时出错。换句话说,用户尝试使用未在方法列表(函数)中列出的方法。
  • OutOfMemoryError:计算需要的内存多于分配的内存。
  • ReadOnlyMemoryError:尝试写入只读内存。
  • OverflowError:当操作结果太大时会发生这种情况。
  • ParseError:解析给定表达式时出现问题。
  • StackOverflowError:当函数调用超出调用范围时会发生这种情况 叠加。
  • SystemError:由于系统调用失败而导致的错误。 TypeError:类型检查的断言失败。当将错误类型的参数传递给函数时,这种情况最常发生。
  • UndefRefError:未知引用。
  • UndefVarError:对不存在的变量进行未知引用。
  • InitError:调用模块的init方法时出现此错误。

有许多类型的异常:

  • ErrorException:发生错误InterruptException:计算中发生外部中断
  • NullException:尝试访问Null值
  • ProcessExitedException:进程结束,因此进一步尝试访问此进程将导致错误

有趣的是,Exception本身就是一个默认在Julia中可用的DataType。 这意味着我们可以通过继承类型来编写自己的自定义异常:

julia> typeof(Exception)
DataType
julia> type CustomException <: Exception
end
julia> typeof(CustomException)
DataType
julia> supertype(CustomException)
Exception

现在让我们逐一讨论一些更有用的函数,这些函数在异常处理时会派上用场。

throw()函数

throw()函数在遇到异常时不会抛出异常。 它会在调用时立即抛出错误。 查看官方文档,这是
它说的是什么:

throw(e)
Throw an object as an exception.

在这里,e是任何对象。 throw会将它转换为异常:

julia> throw("")
ERROR: ""
julia> throw(3+3)
ERROR: 6
julia> throw("some error message")
ERROR: "some error message"
julia> throw(ErrorException("an ErrorException has occurred"))
ERROR: an ErrorException has occurred

要正确抛出TypeError,您必须实际抛出该对象的实例。 可以使用TypeError构造函数创建实例:

julia> function say_hi(name)
if typeof(name) != String
throw(TypeError)
else
println("hi $name")
end
end
say_hi (generic function with 1 method)
julia> say_hi('n')
ERROR: TypeError
Stacktrace:
[1] say_hi(::Char) at ./REPL[155]:3
julia> try
say_hi('n')
catch e
println(typeof(e))
end
DataType

请注意,typeof(e)调用返回DataType。 要更正此问题,请创建TypeError的实例。

julia> function say_hi(name)
if typeof(name) != String
throw(TypeError(:say_hi, "printing name", String, name))
else
println("hi $name")
end
end
say_hi (generic function with 1 method)
julia> say_hi('n')
ERROR: TypeError: say_hi: in printing name, expected String, got Char
Stacktrace:
[1] say_hi(::Char) at ./REPL[158]:3
julia> try
say_hi('n')
catch e
println(typeof(e))
end
TypeError

在这里,我们有一个名为say_hi的函数,它接受一个名称并打印出一个消息,hi $ name,其中的名称将在外部提供。 当我们提供“jack”作为名称时,该功能起作用; 但是,如果提供的名称不是String类型,那么它被编码为抛出一个TypeError,它在传递1作为参数时执行。

虽然这个例子只是为了让我们能够理解throw是如何工作的,但是如果我们要使用多个dispatch,如下面的代码所示,可以很容易地避免使用throw之前的情况:

julia> workspace()
julia> function say_hi(name :: String)
if typeof(name) != String
throw(TypeError)
else
println("hi $name")
end
end
say_hi (generic function with 1 method)
# MethodError will be thrown instead of TypeError
julia> say_hi(1)
ERROR: MethodError: no method matching say_hi(::Int64)
Closest candidates are:
say_hi(::String) at REPL[15]:2

因此,更有用的示例是检查给定名称的长度是否与特定数字匹配。 这是修改后的代码:

julia> workspace()
julia> function say_hi(name :: String)
if length(name) < 5
throw(ArgumentError)
else
println("hi $name")
end
end
say_hi (generic function with 2 methods)
julia> say_hi("joe")
ERROR: ArgumentError
in say_hi(::String) at ./REPL[21]:3
julia> say_hi("david")
hi david

error()函数

此函数可用于引发自定义类型的ErrorException,开发人员希望向最终用户显示该类型。

应该注意,在调试和记录之外通常不鼓励使用该功能。 使用更具体或自定义的异常几乎总是更好。

以前一个throw()函数为例,我们得到:

julia> function say_hi(name :: String)
if length(name) < 5
error("Name less than 5!!!")
else
println("hi $name")
end
end
say_hi (generic function with 1 method)
julia> say_hi("joe")
ERROR: Name less than 5!!!
in say_hi(::String) at ./REPL[33]:3

在这里,我们使用了我们自己的自定义消息,名称小于5 !!!,如果长度小于5,则会在屏幕上打印。

与throw()和error()相比,我们还有两个稍微少用的函数,即info()和warn()。 当我们想告诉最终用户代码中的问题级别时,这两个基本上类似于日志级别:

julia> info("I am an information to the end user")
INFO: I am an information to the end user
julia> warn(" I am a warning issues to the end user")
WARNING: I am a warning issues to the end user

try / catch / finally块

异常处理最重要的部分是使用这些语句。 它们不仅可以提供有效的未知错误安全性,还可以从开发人员的角度提高对代码的控制。 换句话说,如果可能的话,所有编写良好的代码必须包含try / catch块:

julia> try
exponent("alpha")
catch(e)
println(e)
end
MethodError(exponent, ("alpha",), 0x00000000000055aa)

我们已经知道指数不适用于String类型的值; 但是,在这个例子中,我们试图在try块中执行它,如果失败了,catch将捕获并保持异常为e。

最后,我们可以看到代码引发了一个MethodError异常,后来由catch块报告。

当我们需要在代码执行完成后进行清理时,使用finally块。 一旦在数据库表中创建了条目,就可以在关闭数据库连接方面考虑这一点。 该语法将是:

try
...
...
finally
db_connection.close()
end

这包含了我们对异常处理的讨论。 接下来,我们将研究如何在Julia中完成任务。

朱莉娅的任务

任务是一种类似于其他语言的协同程序的功能。 它们帮助我们暂停操作并在需要时恢复。

在正常的顺序代码中,当我们调用一个函数时,让我们说f1,然后调用函数f2,可以理解f2将在f1函数结束时启动。 但是,在整个操作中,一旦它开始执行,我们就无法控制该函数。 Julia中的任务是不同的,因为它允许自己在执行时被中断!

Julia提供了一个名为task()的函数来创建任何函数作为任务(也称为协程)。 这使得该函数的行为与通常不同。 但是,整个过程与函数调用有很大不同。 这有两个主要原因:

  • 在我们想要中断和恢复任务时,此操作根本没有占用空间,因此调用堆栈上没有多余的负载。
  • 没有特定的顺序可以切换任务!

让我们看一个例子,看看我们如何使用这些任务:

julia> function add_one()
a = 1
produce(a)
while true
a += 1
produce(a)
end
end
add_one (generic function with 1 method)
julia> generator = Task(add_one)
Task (runnable) @0x00000001149e9210
julia> consume(generator)
1
julia> consume(generator)
2
julia> consume(generator)
3
julia> consume(generator)
4
julia> consume(generator)
5

让我们开始通过关注这个程序的作用来看问题。 它包含一个名为add_one的函数,它只是将一个名为a的变量加1,而这是在while循环中完成的,它似乎无限运行(如果被调用)。 但是在catch块中,函数add_one将作为参数传递给我们所谓的Task,通过使用task()函数。

但是,还有一个函数,名为produce(),它是一个类似于Python中的yield的函数。 换句话说,它会记住变量的状态。 一旦我们宣布了任务,我们就需要调用它。

这是由另一个名为consume()的函数完成的。 此函数的工作是获取传递给任务的最新(或下一个)值。 因此,当我们呼叫消费者(生产者)时,完整的操作可以分解为:

  • 对于第一次运行,a = 1,生成(a)结果为1,这将传递给consume()函数,该函数返回1。
  • 对于第二次运行,a = 1 + 1。 即2,产生(a)结果为2,然后在调用consume()函数时返回,依此类推。

这是Julia中另一个简单的任务示例。 该函数计算从1到3的数字的平方,并在达到限制时停止:

# valid for julia v0.5
julia> function sample_task()
for i in 1:3
produce(i^2)
end
produce("END")
end
sample_task (generic function with 1 method)
julia> result = Task(sample_task)
Task (runnable) @0x0000000113bfc6d0
julia> consume(result)
1
julia> consume(result)
4
julia> consume(result)
9
julia> consume(result)
"END"
julia> consume(result)
()

概要

我们现在已经成功完成了本章,其中全部是关于Julia的流量控制。 我们看到Julia中的条件和重复评估如何使用关键字和各种结构(如if,while和for),以及讨论如何编写处理带有构造的异常的好代码,例如try / catch。 最后,我们看了如何使用特殊的Task函数在Julia中创建任务或协同程序。

在下一章中,我们将把重点转向学习Julia中的元编程,并理解语言中互操作性的各个方面。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值