JULIA编程规范
在掌握一门语言的基本语法后,就可以一试身手,编写一些程序了。
但实际上,一切才刚刚开始!
在计算资源的各种限制下,在运行指标的各种要求中,若要使用某种语言编写出足够可靠、高效、稳定的程序,还需对该语言细节有更深入的了解。掌握该语言的优劣点,并经过大量的练习与实践,我们才能驾轻就熟,真正控制着某个语言去按照设定的预期目标,去实现想要的程序系统。
为了能够帮助读者在Julia的学习之路上更进一步,避免少些弯路,尽快提高编程技巧,特专辟一章,对Julia语言相关的规范、原则、各种注意事项及语言设计者给出的多方建议进行详尽的介绍。
本章首先介绍编程中不可忽视的重要方面——Julia文档注释系统,然后会在如何编写出高性能Julia程序方面,给出各种注意事项,帮助学习者规避一些问题,还会比较Julia语言与Python、Matlab及R语言的不同之处,也是对其特点的总结;最后在代码风格方面给出建议。
虽然本章可作为选读内容,但从笔者多年的编程经验来看,深刻理解本章内容,能给今后的开发工作带来很大的帮助。
文档注释
代码注释经常会被忽略,尤其是初级程序开发人员,但事实上其重要作用往往超过程序的设计文档。
无论对代码多么熟悉,开发时又是多么花心思,通常隔上半月甚至两周后,开发者一般就会忘记当时的实现逻辑,想不出当时为何这么实现。所以,足够详实的代码注释,尤其关键位置处的重要标识,会给后期的功能优化、修正维护带来极大的裨益。可以说,代码注释的重要性,无论怎么去阐述都不为过。
Julia自v0.4版本之后,便提供了内置的文档注释系统,可以很方便地对函数、类型、对象及语句进行描述,直接支持Markdown格式[[1]],能够生成非常实用、方便的说明文档。不过因篇幅所限,Markdown语法格式的详细介绍需要读者自行查阅,下文仅对Julia别具特色的文档系统进行阐述。
最简单的注释是一句话就可说清楚的单行注释方式,以井号#作为注释内容的前缀,一般放于语句的上一行或当前行尾部。本书前文大量的示例代码已经广泛使用,此处不再赘述。
对于多行注释,一般在注释内容的上下行使用#=与=#两个标记符进行界定,例如:
#=
这是一个多行注释,
这是多行注释的另外一行
=#
function some()
# 单行注释
end
更为强大的注释方式是Julia提供的文档字符串(docstrings)。
在Julia的脚本代码中,类型声明、函数与宏定义等上一行中单独出现的字符串对象都会被认为是注释内容。例如:
"这是对函数foo的注释"
foo(xs::Array) = ...
其中foo()之上的单行字符串会被编译器处理为该函数的注释文档。当然,多行字符串也是支持的,而且遵循Markdown语法格式。例如:
""" # 注释开始
bar(x[, y]) # 原型简述
Compute the Bar index between `x` and `y`. If `y` is missing, compute
the Bar index between all pairs of columns of `x`.
# Examples # 一级标题
```julia-repl # 代码区开始,并紧随Markdown式的语言标识文字
julia> bar([1, 2], [1, 2])
1
``` # 代码区结束
""" # 注释结束
function bar(x, y) ...
其中先简单地给出函数的原型,再详细描述了函数的功能,并用Markdown给出了使用示例。
Julia这种文档字符串方式的注释内容因为与被注释对象上下紧邻,所以两者之间的注释关联会被编译器自动发现,成为内部文档系统的一部分。一旦代码被加载,便可在REPL或IJulia的帮助模式下查看创建的注释文档。
上例通过include()将脚本加载后,在REPL中查看的效果为:
在编写多行文档字符串时,用于界定的三引号"""标识符可单独占一行,这样能使得文本格式更清晰些,即:
"""
...
...
"""
f(x, y) = ...
而不是:
"""...
..."""
f(x, y) = ...
另外,在写文档字符串时,也需留意下每行的字符数量。过长的行会给阅读带来较大的困难。Julia建议遵循代码同样的编写限制,一般以每行92个字符为宜。
在对Julia函数注释时,一般建议注释的内容包括以下几个方面:原型描述、简述或详述、参数列表描述、示例代码、公式或函数引用等。关于各段内容的描述方法,建议如下:
1.原型描述
在文档字符串的头部给出函数的原型描述,简洁地说明函数的调用方法。可以四个空格进行缩进,这样在生成文档时,该原型描述能以Markdown方式被渲染成代码块。
当原型存在可选参数时,描述中尽可能给出完整的定义语法,例如可直接写f(x, y=1);如果参数没有默认值,可用方括号表示,例如f(x[, y])或f(x[, y[, z]])。这种表述看起来会有些困难,可以采用多行方式列出可用的调用原型,例如:
f(x)
f(x, y)
f(x, y, z)
该方式同样可以用于列举函数的多个实现方法。
如果函数存在键值参数,只需在原型描述中使用<keyword arguments>作为占位符即可,例如f(x; <keyword arguments>),然后在# Arguments一节中列出每个键值参数的详细说明。
2.简述与详述
在原型描述之后可给出简述,使用一两行语句简单地描述函数的功能或者用途,以及做什么并返回什么。如果需要,在简述之后隔开一个空行,给出详细的描述,而且可以分成多段进行阐述。不过参数描述不用放在详述中,因为有专门的方式。
描述时尽量简洁,无需过多的衔接转换用词,只需直接描述要点即可。
3.参数描述列表
只在真正需要的情况下提供参数的描述列表,对于简单的函数或者参数名称已经明了地表达了参数的意义时,再在注释中描述只是信息的重复而已,没有必要。但对于复杂的函数,提供参数列表还是必要的,尤其是存在键值参数的时候。
可在文档字符串中使用# Arguments标注开辟专门的一节来描述参数。之后在Markdown项目列表中每行描述一个参数:使用反引号``给出参数原型(包括名称、类型、默认值等),以及参数的作用及意义,还可以包括参数的取值约束等等。例如:
"""
# Arguments
- `n::Integer`: the number of elements to compute.
- `dim::Integer=1`: the dimensions along which to perform the computation.
"""
其中井号#前缀实际创建了Markdown一级标题,反引号对是行内代码标识符。
4.示例代码
可在# Examples一节中以doctest的方式给出示例代码。所谓doctest,是一个独立的代码块,以```jldoctest标注,并包含julia>提示符,给出所有的输入及预期的输出,内容类似于模拟Julia REPL的运行过程,就像在REPL打印出执行过程一样:
"""
# Examples
```jldoctest # 代码块开始
julia> a = [1 2; 3 4] # 模拟输入
2×2 Array{Int64,2}: # 模拟输出
1 2
3 4
``` # 代码块结束
"""
需要注意的是,其中的doctest代码块部分实际完整地模拟了REPL的运行过程,所以对格式非常敏感,任何未能对齐的空格都会影响到在doctest的检验结果。另外,因为doctest中julia>提示符之后的命令会在检验时运行,所以应尽量避免随机数这种不稳定的函数调用;与操作系统机器字节数相关的操作也会影响到doctest的正确验证,也应尽量避免。
但因故示例代码只能是不稳定的(每次运行结果都会不同),则可改用```julia进行标注,这样能够在文档中获得正确的代码块。
5.公式引用
Julia的标识符与代码片段应尽量使用反引号,这样能够在生成的说明文档获得强调显示。若在其中使用LaTeX[[2]]编写公式,应使用双反引号,并尽量采用Unicode字符,而不是使用TeX[[3]]自己的转义字符,例如应采用``α = 1``代替``\\alpha = 1``这种写法。
关于Julia文档系统、LaTex等方面更为详细的内容,限于篇幅,本书不再赘述,读者可参考相关资料。
[[1]] Markdown是一种语法简洁的标记语言,基于纯文本便可创建良好排版的文档;支持章节标题、着重强调、项目列表、表格、脚注引用、图片嵌入、HTML嵌入、LaTex等。也能方便地转为PDF等其他格式。
[[2]] LaTeX是由Leslie Lamport在20世纪80年代开发的排版系统,在TeX的基础上扩展了很多更强大的功能,比Tex更为易用。其官方网站为https://www.latex-project.org
[[3]] TeX是由Donald E. Knuth(高德纳)发明的排版系统,有900多条指令,功能强大而且非常灵活,可以输出专业级的高质量文档。它在学术界十分流行,特别是数学、物理学和计算机领域,是公认的数学公式排得最好的系统,被许多世界一流的出版社如 Kluwer、Addison-Wesley、牛津大学出版社等用来出版书籍和期刊。AMS-TeX与LaTeX系统等都是基于它的著名扩展。
------- 节选自本人新书内容:魏坤著《Julia语言程序设计》,机械工业华章图文出版。
上一篇: 《阿里巴巴Java开发手册》要点整理
下一篇: 微信小程序——图片压缩
推荐阅读
-
JULIA编程规范
-
IOS 多线程编程指南之NSThread
-
JSR168 Portlet规范的中文版 【三】 PLT. 4 概念 博客分类: Portal 浏览器HTML
-
蓝牙射频协议规范
-
多线程编程之join()方法 博客分类: 线程 java线程多线程join编程
-
多线程编程之卫生间 博客分类: 线程 java线程并发厕所卫生间
-
LockSupport详解 | Java并发编程 博客分类: 线程 LockSupportparkBlockjava并发详解
-
多线程编程之理财 博客分类: 线程 java多线程理财生产者消费者
-
《编程之美》--中国象棋将帅问题 博客分类: java 服务 java编程之美算法面试
-
多线程编程之存钱与取钱 博客分类: 线程 java多线程存钱取钱thread