JSRUN 用代码说话

模块

编辑教程

模块

nim支持将一个程序分成若干个模块的概念。每个模块都有自己的文件。模块可以使信息隐藏和分开编译。一个模块可以通过import语句访问其他模块中的符号。只有被星号标记的顶层符号被导出。

# Module A
var
  x*, y: int

proc `*` *(a, b: seq[int]): seq[int] =
  # allocate a new sequence:
  newSeq(result, len(a))
  # multiply two int sequences:
  for i in 0..len(a)-1: result[i] = a[i] * b[i]

when isMainModule:
  # test the new ``*`` operator for sequences:
  assert(@[1, 2, 3] * @[1, 2, 3] == @[1, 4, 9])

上面的模块出口是x和*,不是y。

一个模块的顶层语句在程序开始时执行。例如这可以用来初始化复杂的数据结构。

每个模块都有一个特殊的魔法常数isMainModule,如果这个模块作为主文件被编译,那么这个常数就为真。正如上面的例子所展示的这非常有用对于测试模块内嵌入。

相互依存的模块是可能的,但强烈反对,因为这样没有其他模块时一个模块不能重复使用。

编译模块的算法:

像往常一样编译整个模块,在import语句时递归。 如果这是一个循环只导入已经解析的符号(那是出口);如果一个未知的标识符出现,然后终止。 通过一个例子这是最好的说明:

# Module A
type
  T1* = int  # Module A exports the type ``T1``
import B     # the compiler starts parsing B

proc main() =
  var i = p(3) # works because B has been parsed completely here

main() # Module B
import A  # A is not parsed here! Only the already known symbols
          # of A are imported.   A在这里不解析!只导入A已知的符号

proc p*(x: A.T1): A.T1 =
  # this works because the compiler has already
  # added T1 to A's interface symbol table
  result = x + 1

一个模块的符号要符合module.symbol的语法。即使一个符号是模糊的,它也必须符合modual.symbol语法。一个符号是模糊的如果它被定在了两个不同的模块中(或者更多)并且它们都被第三个模块导入。

# Module A
var x*: string
# Module B
var x*: int
# Module C
import A, B
write(stdout, x) # error: x is ambiguous
write(stdout, A.x) # no error: qualifier used
var x = 4
write(stdout, x) # not ambiguous: uses the module C's x

但是这些规则并不适用于过程或者迭代器。这里应用重载规则:

# Module A
proc x*(a: int): string = $a
# Module B
proc x*(a: string): string = $a
# Module C
import A, B
write(stdout, x(3))   # no error: A.x is called
write(stdout, x(""))  # no error: B.x is called

proc x*(a: int): string = nil
write(stdout, x(3))   # ambiguous: which `x` is to call?

不包括符号

正常情况下import语句会带来所有的输出符号。这可以被限制通过命名符号,它应该使用except修饰语被排除用。

import mymodule except y

From statement

我们已经看到简单的impoer语句只是导入所有的输出符号。另一种可选择的方法是只导入列出的符号是from import语句:

from mymodule import x, y, z

from语句也可以在符号上强行命名空间限定,从而使符号可用,但需要有资格被使用。

from mymodule import x, y, z

x()    # use x without any qualification   使用a没有任何限制
from mymodule import nil
mymodule.x()  #  必须用模块的名称作为前缀修饰x

x() #在这里没有任何资格使用x是一个编译错误

由于模块的名称一般都是很长的描述,你也可以定义一个较短的别名使用当使用限定符号的时候。

from mymodule as m import nil

m.x()         # m is aliasing mymodule  m是mymodule的别名

Include statement

include语句与导入一个模块有一些根本上的不同:include仅仅包含一个文件的内容,include语句将一个大的模块分割成几个文件是有用的。

include fileA, fileB, fileC
JSRUN闪电教程系统是国内最先开创的教程维护系统, 所有工程师都可以参与共同维护的闪电教程,让知识的积累变得统一完整、自成体系。 大家可以一起参与进共编,让零散的知识点帮助更多的人。
X
支付宝
9.99
无法付款,请点击这里
金额: 0
备注:
转账时请填写正确的金额和备注信息,到账由人工处理,可能需要较长时间
如有疑问请联系QQ:565830900
正在生成二维码, 此过程可能需要15秒钟