• 模块
    • Import语句
    • Include语句
    • 导入的模块名
    • 从目录中集体导入
    • 伪import/include目录
    • From import语句
    • Export语句

    模块

    Nim支持通过模块概念将程序拆分为多个部分。 每个模块都需要在自己的文件中,并且有自己的 命名空间 。 模块启用 信息隐藏 and 分开编译 。 模块可以通过 import 语句访问另一个模块的符号。 递归模块依赖 是允许的,但有点微妙。 仅导出标有星号(*)的顶级符号。 有效的模块名称只能是有效的Nim标识符(因此其文件名为 标识符.nim )。

    编译模块的算法是:

    • 像往常一样编译整个模块,递归地执行import语句
    • 如果有一个只导入已解析的(即导出的)符号的环;如果出现未知标识符则中止 这可以通过一个例子来说明:
    1. # 模块A
    2. type
    3. T1* = int # 模块A导出类型 ``T1``
    4. import B # 编译器开始解析B
    5.  
    6. proc main() =
    7. var i = p(3) # 因为B在这里被完全解析了
    8.  
    9. main()
    1. # 模块 B
    2. import A # 这里没有解析A,仅导入已知的A符号。
    3.  
    4. proc p*(x: A.T1): A.T1 =
    5. # 这是有效的,因为编译器已经将T1添加到A的接口符号表中
    6. result = x + 1

    Import语句

    import 语句之后,可以跟随模块名称列表或单个模块名称后跟 except 列表以防止导入某些符号:

    1. import strutils except `%`, toUpperAscii
    2.  
    3. # 行不通:
    4. echo "$1" % "abc".toUpperAscii

    没有检查 except 列表是否真的从模块中导出。 此功能允许针对不导出这些标识符的旧版本模块进行编译。

    Include语句

    include 语句与导入模块有着根本的不同:​​它只包含文件的内容。 include 语句对于将大模块拆分为多个文件很有用:

    1. include fileA, fileB, fileC

    导入的模块名

    可以通过 as 关键字引入模块别名:

    1. import strutils as su, sequtils as qu
    2.  
    3. echo su.format("$1", "lalelu")

    然后无法访问原始模块名称。 符号 path/to/module"path/to/module" 可用于引用子目录中的模块:

    1. import lib/pure/os, "lib/pure/times"

    请注意,模块名称仍然是 strutils 而不是 lib/pure/strutils 因此 无法 做:

    1. import lib/pure/strutils
    2. echo lib/pure/strutils.toUpperAscii("abc")

    同样,以下内容没有意义,因为名称已经是 strutils

    1. import lib/pure/strutils as strutils

    从目录中集体导入

    语法 import dir / [moduleA, moduleB] 可用于从同一目录导入多个模块。

    路径名在语法上是Nim标识符或字符串文字。如果路径名不是有效的Nim标识符,则它必须是字符串文字:

    1. import "gfx/3d/somemodule" # 在引号中因为'3d'不是有效的Nim标识符

    伪import/include目录

    目录也可以是所谓的“伪目录”。当存在多个具有相同路径的模块时,它们可用于避免歧义。

    有两个伪目录:

    1. std: std 伪目录是Nim标准库的抽象位置。 例如,语法 import std / strutils 用于明确地引用标准库的 strutils 模块。

    2. pkg: pkg 伪目录用于明确引用Nimble包。 但是,对于超出本文档范围的技术细节,其语义为:使用搜索路径查找模块名称但忽略标准库位置 。 换句话说,它与 std 相反。

    From import语句

    from 语句之后,一个模块名称后面跟着一个 import 来列出一个人喜欢使用的符号而没有明确的完全限定:

    1. from strutils import `%`
    2.  
    3. echo "$1" % "abc"
    4. # 可能:完全限定:
    5. echo strutils.replace("abc", "a", "z")

    如果想要导入模块但是想要对 module 中的每个符号进行完全限定访问,也可以使用 from module import nil

    Export语句

    export 语句可用于符号转发,因此客户端模块不需要导入模块的依赖项:

    1. # 模块B
    2. type MyObject* = object
    1. # 模块A
    2. import B
    3. export B.MyObject
    4.  
    5. proc `$`*(x: MyObject): string = "my object"
    1. # 模块C
    2. import A
    3.  
    4. # B.MyObject这里已经被隐式导入:
    5. var x: MyObject
    6. echo $x

    当导出的符号是另一个模块时,将转发其所有定义。您可以使用 except 列表来排除某些符号。

    请注意,导出时,只需指定模块名称:

    1. import foo/bar/baz
    2. export baz