Julia基础知识
在本章中,我们将学习并行计算所需的Julia基本部分:
- 变量
- 函数
- 数组
在Julia中使用jupyter笔记本,运行单元格可以使用shift + enter,也可以使用运行按钮。
运行第一个单元格可以看到,显示了最后一行的值,我们可以用分号抑制输出,尝试执行第二个单元格,可以发现没有输出。
单元格的顺序也很重要,以相反的顺序运行下边的两个单元格将不起作用。
变量
Julia中变量的用法与python十分相似,但是与C/C++等有很大不同。
创建变量
变量是与值关联(绑定)的名称,我们像往常一样将变量与值用=关联起来。
a = 1
分配变量时,右侧的值不会被复制到变量中,它只是名称与值的关联。
重新分配变量
我们可以重新分配一个变量,甚至可以使用另一种类型的值。但是,由于性能原因,请避免更改变量。
a = 2
a = 1.0
a = "Hi!"
依次输出2、1.0、Hi!
Unreachable Objects
当一个对象不再与变量关联时,用户就无法访问它。例如,当我们重新分配变量时,就会发生这种情况。另一种情况是局部变量(例如函数中的局部变量)超出范围。以下行分配一个大数组并将其分配给变量a。
如果我们将变量重新分配另一个值,则大数组将无法访问。
垃圾收集器
幸运的是,Julia有一个垃圾收集器,可以释放无法访问的对象。垃圾收集不会立即发生,而是在某个时刻发生。您也可以显式调用垃圾收集器,但是在实践中几乎从未这样做过。
GC.gc()
类型声明是可选的
Julia知道与变量关联的对象的类型。
如果需要,我们可以对类型进行注释,但是这不会提高性能,除非在非常特殊的情况下。因此,实际上并没有对类型进行任何注释。
如果用类型注释变量,则它不能引用其他类型的对象。
变量名
在Julia中选择变量名称有很大的灵活性,我们可以在变量和函数名称中使用UTF-8编码的字符。
我们还可以使用希腊字母和其他数学符号,此处就不赘述了。
函数
Julia在很大程度是一种函数式编程语言。因此,Julia更关注函数而不是类型。这与面向对象形成鲜明对比,面向对象更以类为中心。因此,我们不需要了解Julia类型系统的系列来学习并行编程,但是我们需要对Julia函数的工作原理有相当深的了解。
定义函数
函数的定义如下面所示,end是十分必要的,return是可选的,默认返回最后一行的值,建议使用缩进。
Broadcast syntax
我们可以使用broadcast语法将函数逐个元素应用于数组。
数学运算符也可以被广播,直接将向量相乘a*b是行不通的。如果我们想逐个元素相乘,可以使用如下的广播版本。
在定义这个函数之后,最后一行的x返回多少?结果是1
Reference
正如我们看到的,变量是按照值传递的,通过引用传递变量需要使用引用完成。
定义函数(更短的方法)
对于短函数,我们可以跳过function和end关键字。
匿名(lambda)函数
我们可以把函数分配给变量,因此在许多情况下函数不需要函数名。我们可以简单地创建一个匿名函数(即没有名称的函数)并将其分配给一个变量。
add_anonymous不是函数名称,它只是与没有函数名称的函数关联的变量。
函数是第一类对象
我们可以像处理任何其他类型的对象一样使用Julia函数,例如,我们可以将函数分配给变量。然后就可以使用变量名称调用该函数。
我们还可以创建一个函数数组,这在python中不适用。
要调用数组中的特定函数,我们对数组进行索引,然后调用返回的函数。
高阶函数
高阶函数是接受和/或返回其他函数的函数,例如Julia中的count()函数。
例如,我们可以传递一个用户定义的函数来计算数组中偶数元素的数量:
Do块
还有另一种定义匿名函数的方法。如果一个函数在其第一个参数中接受一个函数,例如count,我们可以在调用第一个函数时跳过第一个参数,并定义我们想要在do块中传递的函数。这很有用,例如,如果我们想定义一个多行匿名函数,接下来的两个单元格是等效的。
返回多个值
Julia函数始终返回单个变量。要返回多个值,我们可以将它们包装在一个元组中。
可变数量的输入参数
Julia还支持具有多个参数的函数,args是一个包含所有参数的元组:
位置参数和关键字参数
函数可以像在python中一样组合位置参数和关键字参数,但是在Julia中关键字参数以;开头。
-
位置参数:这些参数是按照它们在函数签名中的位置顺序传递的参数。在调用函数时,你必须按照函数定义的参数顺序提供这些参数。
-
关键字参数:这些参数是使用参数名明确传递的参数。与位置参数不同,你可以不按照参数在函数签名中的位置顺序传递它们,只需指定参数名即可。
可选参数
我们可以为参数提供默认值,使其成为可选的。
请思考最下面的x应该是什么值?
数组
Julia支持多维数组,它们与python中的Numpy十分类似。
Array literals
我们可以使用数组文字从给定值创建数组。
下面的代码创建一个3个整数的向量,Julia中的向量与列表没有区别。
数组初始化
我们可以创建所有条目等于0、1或特定给定值的数组。该值可以是任何Julia对象,甚至是函数。
数组推导式
我们还可以使用数组推导中的循环来创建数组中的项目。
索引
我们还可以通过索引数组来获取和设置数组的项目。
不可变的元素类型
一旦设置,数组中的元素类型就无法更改。如果我们尝试使用不同类型的对象设置项目,Julia将尝试进行转换。这可能会失败,具体取决于传递的值。
任何元素类型的数组
固定元素类型的数组看起来很死板,python的列表没有这个限制。但是我们可以使用Any类型的数组,它看起来和python列表一样灵活,甚至更灵活,因为它们可以包含函数。
循环
循环依次访问元素,第二个循环访问从1到数组长度的整数,并在每个整数处对数组进行索引。
第三个循环“枚举”数组中的项目。
数组索引默认从1开始
使用过程中需要注意。
切片分配一个新的数组
数组视图
如果要修改原始数组,使用view。
练习题
实现一个ex1(a)
查找数组中最大项的函数a
。它应该返回最大的项目及其在数组中的相应位置。如果有多个最大元素,则返回第一个。假设数组不为空。在下一个单元格中实现该函数。使用另一个测试您的实现。
实现一个函数ex2(f,g),接受两个函数f(x)和g(x),返回一个新的h(x)表示这两个函数的和。
在Julia中,x -> f(x) + g(x)
是一个匿名函数(Anonymous Function)或 Lambda 函数的表示方式。它定义了一个以 x
为参数的函数,该函数执行的操作是将 f(x)
和 g(x)
相加。
具体来说,x -> f(x) + g(x)
表示一个函数,它接受一个参数 x
,然后计算 f(x) + g(x)
的值,并返回这个值作为函数的结果。这允许你在不创建显式函数名称的情况下,定义一个临时的函数用于特定的计算。
在前面的例子中,我们使用 ex2
函数创建了一个新的函数 h
,它的定义是 x -> f(x) + g(x)
,这意味着当你调用 h(x)
时,它将计算 f(x) + g(x)
的结果。这是一种非常灵活的方式来创建临时函数,特别适用于需要将函数作为参数传递或将函数作为返回值的情况。