1.1 初识 Julia
1.1.1 为什么要有 Julia
首先,我们要知道的是,Julia 是一门计算机编程语言。也就是说,我们可以使用符合 Julia 语言规范的代码来编写程序。这些程序可以用于纯粹的数学和科学计算、存取本地文件、通过网络收发数据,等等。虽然 Julia 针对各种科学计算任务做了特别的设计和优化,但它也适用于通用目的的编程。
科学计算往往对代码的表现力和性能都有着较高的要求。然而,一些善于科学计算的编程语言(如 Python 和 R)却都在这两个方面有所欠缺。不过,我相信它们的流行必有其原因。而且,我也很喜欢这些编程语言。它们是我的编程工具箱中必不可少的一部分,尤其是 Python。
现代语言设计和编译器技术基本上能让我们省去性能调试的工作量,并且可以提供一个单一的环境让我们打造程序原型和有效部署高性能的应用。Julia 编程语言就是在此基础之上诞生的。Julia 是一门灵活的动态编程语言,但其性能堪比传统的静态编程语言。
1.1.2 主要特性
Julia 拥有可选的类型标注(type annotation)、多重分派(multiple dispatch)机制,以及优良的性能。它还借由 LLVM 实现了类型推断和即时(JIT)编译。Julia 是多范式的,融入了命令式、函数式和面向对象编程的特性。Julia 为高级数值计算提供了足够的易用性和表现力。当然,Julia 也适用于通用编程。为此,它从那些流行的动态编程语言(包括 Lisp、Perl、Python、Lua 和 Ruby)中借鉴了很多。
Julia 与典型的动态编程语言之间最大的区别在于:
- Julia 的 Base 包和标准库都是由 Julia 语言编写的。这包括像整数运算那样的基本操作。也就是说,Julia 实现了一定程度的自举。
- Julia 拥有丰富的类型构造和对象描述方式,并且代码中的类型标注是可选的。
- Julia 拥有多重分派机制。它可以根据参数类型的不同去调用衍生自同一个函数定义的不同方法。并且,它还可以针对不同的参数类型自动生成有效的专用代码。
- Julia 的性能优良,并已接近那些静态编译的编程语言(如 C 语言)。
虽然那些动态编程语言从表面上看是“无类型的”,但是它们在内部却是“有类型的”。这些内部的类型一般都是在其读取代码后附加上去的。不过,由于这些语言的代码缺少类型标注,所以它们并不能向编译器明确地指示某个值的类型,甚至都不能显式地提及类型。另一方面,静态编程语言虽然可以(且必须)为编译器指示值的类型,但这些类型往往只在编译时存在,并不能在运行时操纵或表示。而在 Julia 中,类型本身就是运行时的对象。并且,这些类型也可以被用来向编译器传达信息。
我们可以不显式地使用类型标注或多重分派。但这些都是 Julia 最核心的特性,我还是建议你利用它们来改进你的代码。这样的话,你的代码的表现力会更强,并且更容易阅读。
1.1.3 更多的特性
Julia 的目标是成为一门易用、强大和高效的编程语言。除了上述的优点之外,Julia 相对于其他类似系统的优势还包括:
- 可供免费使用,并且开源(遵从 MIT 协议)
- 用户自定义的类型与内置的类型一样快速和紧凑
- 无需担心向量化代码的性能,被拆解后的代码速度会很快
- 已为并行计算和分布式计算做了优化设计
- 拥有轻量级的“绿色”线程(也就是协程)
- 拥有可选择使用但功能强大的类型系统
- 拥有针对于数字和其他类型的转换和提升方法,并且是优雅和可扩展的
- 有效支持 Unicode,包括但不限于 UTF-8
- 可以直接调用 C 程序中的函数,无需额外封装或者特殊的 API
- 可以管理其他进程,强大如 Shell
- 拥有类似于 Lisp 的宏,以及其他的元编程工具
顺便说一句,由于 Julia 的编译器不同于 Python 和 R 中的解释器,所以你在起初也许并不能体会到 Julia 的性能优势。如果你发现一些程序运行起来比较慢,那么我强烈建议你去阅读官方文档中的性能秘诀。一旦你理解了 Julia 是怎样工作的,那么写出性能堪比 C 程序的代码就比较容易了。