或许你根本没听说过还有这么一门语言,我也是最近才接触到它,瞬间就被它的高效简洁所吸引,这里所指的高效,同时包含了编码与执行两层含义。我曾经非常想在 Java 或 Kotlin 内直接书写数学公式,因此也学习了 MPS 等奇怪的东西,比如说这样的(图片来源为 JetBrains MPS Intro):
虽然在这种情况下写代码的确是累了点,但是效果很好,能够很直观的看出来想要做的事情。
当用上 Julia 之后,就可以直接扔掉 MPS 了,你可以用很简单的方式,在 Julia 里编写数学公式:
julia> x = 3
julia> y = 2x^2 + 3x - 1
julia> println(y)
julia> z = √2
julia> println(z)
写个根号都那么任性!
既然要拿它来进行开发了,那自然逃不了搭建开发环境等事。好在 Julia 提供了非常简单搭建手册,直接照做就行了(点击查阅)。
搭过一遍后,我发现我这种 Idea 党完全用不惯 Atom,还是更加倾向于在 Idea 里直接搭建。不得不说,JetBrains 全家桶真的是万能的,直接就找到了 Julia 的插件:
安装后只需要配置 Julia 的可执行程序路径即可,比如说在 Mac 下是 /Applications/Julia-x.y.app/Contents/Resources/julia/bin/julia
。于是环境就搭好了,可以愉快的玩耍了。
对于我来说,学习一门新的语言,我都会从它的特性开始入手,比如说特定的数据类型:
julia> x = √Complex(-1)
0.0 + 1.0im
是不是发现新大陆了?在其他的编程语言里,对 -1 开根号必然是报错的,然而在 Julia 里,居然支持虚数单位,这个特性已经可以决定 Julia 必然在科学计算领域里能大有作为。同样的,还有一些常规语言不具备的概念性的东西:
julia> x = 1 / Inf
0.0
julia> y = 0 * Inf
NaN
在这里的 Inf 就是无穷大(也有负无穷大),而 NaN 即是表示 并非是一个数字(Not a Number)
。这些概念的引入,使得 Julia 更加适合被用在科学计算上。当然了,Julia 所包含的并不仅仅有这些概念而已,通过查阅手册,可以了解到更多的令人激动的特性(点此查阅手册)。
下面也要尝试一下,Julia 对于常规编程的支持是否友好,我选择的是网络请求和 JSON 解析的能力。
Julia 已拥有很多第三方库,可以直接在包管理工具内进行安装,默认是不安装的。在安装的过程中,也有可能会出现问题,多是因为国内
网络的问题,导致一些包无自法下载,请自行寻找解决方案。在网络完备的前提下,使用以下命令可以完成对网络请求库,以及 JSON 解析库的安装:
julia> using Pkg
julia> Pkg.add("HTTP")
julia> Pkg.add("JSON")
julia> Pkg.build("MbedTLS")
然后只需要一点点代码,就能完成一个简易的请求了:
using HTTP
using JSON
httpRequest(url, cb) = (
ret = HTTP.request("GET", url);
cb(ret.status, String(ret.body))
)
httpRequest("http://httpbin.org/ip", (code, body) -> (
println(code);
println(body);
json = JSON.parse(body);
ip = json["origin"];
println(ip)
))
可以很明确的看到,Julia 和 Kotlin 一样,都把函数视为一等公民,并且 Julia 更智能,并不需要传入函数的定义。在这一点是,是仁者见仁的,因为这样的特性存在,也强迫我们必须写较多的注释,否则后期自己的代码都无法维护了。
本地化编译,这是一个非常有用的特性,可以让执行效率变得更高,同时更容易分发软件。在 Julia 里做本地化编译目前还是有一些麻烦的,官方提供的编译工具并不那么好用,如下:
julia> using Pkg
julia> Pkg.add("PackageCompiler")
julia> using PackageCompiler
julia> build_executable("sample.jl")
这两句代码在一开始绝对会让你体会到什么叫生不如死,因为编译时会报错:
ERROR: Unexpected format of "Base.julia_cmd()", you may be using an incompatible version of Julia
查了一下 github 的提交记录,发现最新的 PackageCompiler 0.6.0
已经可以适配 Julia 1.1
了,然而我们通过 Pkg 安装来的 PackageCompiler 却是 0.5.1
的,必须先进行升级:
julia> ]
pkg> st
pkg> up PackageCompiler
此时就可以把 PackageCompiler 升级到最新版本,可以进行编译了,切记,在编译前重启 REPL,否则加载到的依然是老版本的包。
对于 Julia 来说,要编译一个本地化应用,需要一个与 C 一致的 main 函数,作为程序的执行入口,所以我们可以把代码修改成这样:
module GetIP
import HTTP
import JSON
httpRequest(url, cb) = (
ret = HTTP.request("GET", url);
cb(ret.status, String(ret.body))
)
Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
httpRequest("http://httpbin.org/ip", (code, body) -> (
json = JSON.parse(body);
ip = json["origin"];
println(ip)
))
return 0
end
end
然后在 Julia 命令行下进行编译就可以了:
julia> using PackageCompiler
julia> build_executable("sample.jl")
经过漫长的等待(至少1分钟),就可以看到原本可执行程序已生成。就目前来看,编译效率实在是非常低,并且在编译结果中还带有一大堆的依赖库,对发布程序造成一些不便。
不过不论如何,我们已经成功上手了 Julia,可以使用它来做一些开发了,比较看重它的跨平台特性(虽然还没体验到)以及对科学计算的能力,同样的,极其方便的代码编写方式,良好的语言胶水特性,也是非常到位的继续使用的理由。