6.2 符号

我们尽量保持本书符号的一致性。 这会使阅读和编写代码更容易。 我们可以将符号定义为三个部分。

6.2.1 Julia 风格指南

首先,我们尝试遵循 Julia 风格指南 中的约定惯例。 更重要的是,要编写函数而不是脚本(也可查阅 Section 1.3)。 另外,我们使用与 Julia base/ 模块一致的命名约定,即:

  • 模块采用驼峰命名法: module JuliaDataSciencestruct MyPoint。 (之所叫驼峰命名法,是因为单词的首字母大写,如 “iPad” 或 “CamelCase”, 这使得单词看起来像驼峰。)
  • 函数名全部小写,并用下划线分隔单词。 不过也允许在命名函数时省略分隔符。 例如,这些函数名都符合约定: my_functionmyfunctionstring2int

同时,避免在条件语句中使用括号,即写为 if a == b 而不是 if (a == b),并且每级缩进使用 4 个空格。

6.2.2 Blue 风格指南

Blue 风格指南 在默认的 Julia 风格指南基础上增加了更多的约定。 一些规则可能听起来有点古板,但我们发现这样能提高代码的可读性。

根据风格指南,我们具体坚持:

  • 每行代码最多 92 字符(Markdown 文件允许更长的行)。

  • 使用 using 加载模块,且每行最多加载一个。

  • 行尾无空格。 行尾的空格会使代码更改检查更加困难,因为虽然它们不会修改代码行为,但会显示为更改。

  • 避免括号内的多余空格。 因此,要写为 string(1, 2) 而不是 string( 1 , 2 )

  • 应避免全局变量。

  • 尝试将函数名压缩至一到两个词。

  • 使用分号 ; 来说明参数是否为关键字参数。 例如,使用 func(x; y=3) 而不是 func(x, y=3)

  • 避免使用多个空格来对齐对象。 所以,应该写

    1. a = 1
    2. lorem = 2

    而不是

    1. a = 1
    2. lorem = 2
  • 当合适时,我们应在双目运算符两侧增加空格,例如, 1 == 2y = x + 1

  • 缩进三引号和三反引号:

    1. s = """
    2. my long text:
    3. [...]
    4. the end.
    5. """
  • 不要省略浮点数中的零(即使 Julia 允许这样做)。 因此,写为 1.0 而不是 1. ,写为 0.1 而不是 .1

  • 在 for 循环中使用 in,而不是 = (即使 Julia 允许这样做)。

6.2.3 我们的补充

  • 在行文时,我们将使用 M.foo 引用 M.foo(3, 4),而不是使用 M.foo(...)M.foo()
  • 当讨论软件包时,如 DataFrames 包,我们每次都会明确地写为 DataFrames.jl。 这使得可以非常容易地定位正在讨论的包。
  • 对于文件名, 我们坚持使用 “file.txt”,而不是 file.txt 或 file.txt,因为这种形式与代码保持一致。
  • 对于表中的列,如列 x,我们坚持使用 :x,因为这种形式与代码保持一致。
  • 不要在行内代码使用 Unicode 符号。 这只是一个 PDF 生成中的 bug,但现在我们必须解决它。
  • 每个代码块前面的行以冒号 (:) 结尾,表示此行属于该代码块。

6.2.3.1 加载符号

在不使用 REPL 时,我们更喜欢显式加载符号,即更喜欢使用 using A: foo 而不是 using A(另请查阅 JuMP Style Guide (2021))。 在此上下文中,符号表示对象的标识符。 例如,即使看起来不正常, 但本质上 DataFrameπCSV 都是符号。 在使用诸如 isdefined 这样的 Julia 方法时,我们发现了这一点:

  1. isdefined(Main, :π)
  1. 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,其进行的是非破坏性更新。 在这种非破坏性更新下,你不用担心你的包会产生破坏,即抛出错误或改变行为。 如果包 A0.2 变化到 1.0, 这意味着破坏性更新,然后你预计需要对你的包做一些修改,然后才能使包 A 再次正常运行。 然而,导出额外符号视为非破坏性更新。 所以,在隐式加载符号时, 非破坏性更新会破坏你的包。 这就是为什么显式加载符号是一种很好的风格实践。

CC BY-NC-SA 4.0 Jose Storopoli, Rik Huijzer, Lazaro Alonso, 刘贵欣 (中文翻译), 田俊 (中文审校)