我们尽量保持本书符号的一致性。 这会使阅读和编写代码更容易。 我们可以将符号定义为三个部分。
首先,我们尝试遵循 Julia 风格指南 中的约定惯例。 更重要的是,要编写函数而不是脚本(也可查阅 Section 1.3)。 另外,我们使用与 Julia base/
模块一致的命名约定,即:
module JuliaDataScience
, struct MyPoint
。 (之所叫驼峰命名法,是因为单词的首字母大写,如 “iPad” 或 “CamelCase”, 这使得单词看起来像驼峰。)my_function
, myfunction
和 string2int
。同时,避免在条件语句中使用括号,即写为 if a == b
而不是 if (a == b)
,并且每级缩进使用 4 个空格。
Blue 风格指南 在默认的 Julia 风格指南基础上增加了更多的约定。 一些规则可能听起来有点古板,但我们发现这样能提高代码的可读性。
根据风格指南,我们具体坚持:
每行代码最多 92 字符(Markdown 文件允许更长的行)。
使用 using
加载模块,且每行最多加载一个。
行尾无空格。 行尾的空格会使代码更改检查更加困难,因为虽然它们不会修改代码行为,但会显示为更改。
避免括号内的多余空格。 因此,要写为 string(1, 2)
而不是 string( 1 , 2 )
。
应避免全局变量。
尝试将函数名压缩至一到两个词。
使用分号 ;
来说明参数是否为关键字参数。 例如,使用 func(x; y=3)
而不是 func(x, y=3)
。
避免使用多个空格来对齐对象。 所以,应该写
a = 1
lorem = 2
而不是
a = 1
lorem = 2
当合适时,我们应在双目运算符两侧增加空格,例如, 1 == 2
或 y = x + 1
。
缩进三引号和三反引号:
s = """
my long text:
[...]
the end.
"""
不要省略浮点数中的零(即使 Julia 允许这样做)。 因此,写为 1.0
而不是 1.
,写为 0.1
而不是 .1
。
在 for 循环中使用 in
,而不是 =
或 ∈
(即使 Julia 允许这样做)。
M.foo
引用 M.foo(3, 4)
,而不是使用 M.foo(...)
或 M.foo()
。DataFrames.jl
。 这使得可以非常容易地定位正在讨论的包。file.txt
或 file.txt,因为这种形式与代码保持一致。x
,我们坚持使用 :x
,因为这种形式与代码保持一致。在不使用 REPL 时,我们更喜欢显式加载符号,即更喜欢使用 using A: foo
而不是 using A
(另请查阅 JuMP Style Guide (2021))。 在此上下文中,符号表示对象的标识符。 例如,即使看起来不正常, 但本质上 DataFrame
、π
和 CSV
都是符号。 在使用诸如 isdefined
这样的 Julia 方法时,我们发现了这一点:
isdefined(Main, :π)
true
接下来使用 using
时会变得显式,另外更喜欢使用 using A: foo
而不是 import A: foo
,因为后者更容易意外地扩展 foo
。 注意这不仅仅是针对 Julia 的建议: Python 也不鼓励通过 from <module> import *
隐式加载符号 (van Rossum et al., 2001)。
显式加载的重要性与语义版本控制有关。 结合语义版本控制 (http://semver.org) 后,版本号将关系到包是否存在 破坏性 更新。 例如,当包 A
的版本号从 0.2.2
变化到 0.2.3
,其进行的是非破坏性更新。 在这种非破坏性更新下,你不用担心你的包会产生破坏,即抛出错误或改变行为。 如果包 A
从 0.2
变化到 1.0
, 这意味着破坏性更新,然后你预计需要对你的包做一些修改,然后才能使包 A
再次正常运行。 然而,导出额外符号视为非破坏性更新。 所以,在隐式加载符号时, 非破坏性更新会破坏你的包。 这就是为什么显式加载符号是一种很好的风格实践。