Nim语言的模块化编程

前言

Nim支持把一大段程序分成若干个模块

一个模块就是一个源代码文件

每个模块都拥有它自己的名称空间

模块化可以起到封装(信息隐藏)和分步编译的作用

 

一个模块可以通过import语句获得另一个模块的符号

nim语言允许模块间的循环引用,

只有用星号(*)标记的顶级符号才会被导出给其他模块。

模块名和文件名相同,模块名的命名方式和nim编程语言的标识符命名方式相同

 

编译器编译模块的规则如下:

  • 按照import的导入顺序,编译模块

  • 如果存在循环引用,那么就只导入顶级符号(已解析的符号),如果编译器发现未知的标识符,那么就停止编译

请看下面的例子:

模块A的代码:

1
2
3
4
5
6
7
8
9
# 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()

模块B的代码:

1
2
3
4
5
6
7
8
# Module B
import A  # A is not parsed here! Only the already known symbols
          # of A are imported.
 
proc p*(x: A.T1): A.T1 =
  # this works because the compiler has already
  # added T1 to A's interface symbol table
  result = + 1

看起来是不是很厉害呢?!

 

import语句

可以通过import导入一个或多个模块

(导入多个模块的话,只要在import后面跟上模块的名字即可,模块的名字用逗号隔开)

可以用except排除一个或多个模块中的符号

请看下面的示例代码:

1
2
3
4
import strutils except `%`, toUpper
 
# doesn't work then:
echo "$1" % "abc".toUpper

注意:如果导入的模块中并没有导出排除的标识符的话,nim编译器是不会给出报警或异常的

 

include语句

include语句完全不同于import语句,

include语句会迫使编译器把一个文件的源码“包含”到另一个文件中。

需要把一个文件拆分成多个文件的时候include语句很有用

1
include fileA, fileB, fileC

 

import语句中的模块名

import语句中的模块名可以设置别名

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

如果你用了别名的话,那么原来的模块名称就不起作用了

如果一个模块在某个子目录中

可以使用如下三种办法来导入该模块

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

注意:虽然模块在子目录中,但是模块名并不包含路径

下面的代码是错误的:

1
2
import lib.pure.strutils
echo lib.pure.strutils

下面这种代码设置也没有任何意义

1
import lib.pure.strutils as strutils

 

from...import...语句

如果你只想导入某一个模块的指定符号,那么你就可以使用这种语句

来看下面的代码:

1
2
3
4
5
from strutils import `%`
 
echo "$1" % "abc"
# 但开发人员还是可以用完全限定符调用这个模块的其他方法:
echo strutils.replace("abc""a""z")

如果你想迫使开发人员必须在主调模块中使用完全限定符来调用被调模块的符号

那么你可以使用,下面这种方法

1
rom strutils import nil

 

Export语句

下来看下面三个模块的代码

1
2
# module B
type MyObject* = object
1
2
3
4
5
# module A
import B
export B.MyObject
 
proc `$`*(x: MyObject): string = "my object"
1
2
3
4
5
6
# module C
import A
 
# B.MyObject has been imported implicitly here:
var x: MyObject
echo($x)

模块A把模块B中的符号导出出来了

这样模块C就不用再导入模块B了

posted @   liulun  阅读(2479)  评论(3编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
历史上的今天:
2009-08-07 PL/SQL学习笔记-触发器
点击右上角即可分享
微信分享提示