模块

依靠模块概念 Nim 支持将程序拆分成小块。每个模块单独一个文件,有其独立的 namespace “命名空间”。 模块为 information hiding “信息隐藏”和 separate compilation “独立编译”提供了可能。一个模块可以通过 import 语句访问另一个模块里的符号。允许 Recursive module dependencies “递归模块依赖”,但是略微复杂。只会导出带了星号( * )标记的顶层符号。 只有合法的 Nim 标识符才能作为模块名(所以对应的文件名是 identifier.nim )。

编译模块的算法如下:

  • 递归地追随导入语句正常编译整个模块。
  • 如果发现成环,只导入已经完成语法分析的(且被导出的)符号;如果遇到未知标识符就中止。

最好用一个例子来演示(译者注:代码里的注释描述了编译模块 A 时编译器的行为):

  1. # 模块 A
  2. type
  3. T1* = int # 模块 A 导出了类型 `T1`
  4. import B # 编译器开始分析模块 B
  5. proc main() =
  6. var i = p(3) # 由于此处模块 B 已经完成语法分析,所以没有问题
  7. main()
  1. # 模块 B
  2. import A # 此时模块 A 未完成语法分析,只会导入模块 A 中目前已知的符号
  3. proc p* (x: A.T1): A.T1 =
  4. # 编译器已把 T1 添加到 A 的接口符号表,所以这么写没问题
  5. result = x + 1