Nim教程【十一】
引用类型和指针类型
不同的引用可以只想和修改相同的内存单元
在nim中有两种引用方式,一种是追踪引用,另一种是非追踪引用
非追踪引用也就是指针,指向手动在内存中分配的对象;
追踪引用指向一个垃圾收集的对象;
非追踪引用是不安全的
然而对于一些低级操作(比如说访问硬件),非追踪引用是不可避免的
追踪引用用ref关键词声明
非追踪引用用ptr关键词声明
可以用[]来解包一个引用(访问一个元组或对象域时要用到)
请看下面的代码:
1 2 3 4 5 6 7 8 9 10 | type Node = ref NodeObj NodeObj = object le, ri: Node data: int var n: Node new(n) n.data = 9 # no need to write n[].data; in fact n[].data is highly discouraged! |
上面代码中最后一行,没必要写成n[].data
使用new()来创建一个新的追踪对象
可以使用alloc或dealloc或realloc函数处理非追踪对象
如果一个引用没有指向任何东西,那么他的值为nil
proc方法指针类型
方法类型是一个方法的指针
(译注:一般函数式的语言中都有这个特性哦)
方法类型的变量默认值为nil
来看一下下面的代码
1 2 3 4 5 6 7 8 9 | proc echoItem(x: int ) = echo(x) proc forEach(action: proc (x: int )) = const data = [ 2 , 3 , 5 , 7 , 11 ] for d in items(data): action(d) forEach(echoItem) |
模块
nim允许把一个程序分成若干个模块
一个模块就是一个文件
模块可以起到隐藏信息的作用(译注:面向对象的封装)
模块可以起到分开编译的作用
一个模块可以用import语句导入另一个模块的符号
在一个模块中,只有用星号标记的符号,才能导出给另一个模块
来看看下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 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和方法*
在程序开始执行的时候就会执行模块的顶层语句,
程序员可以利用nim的这个特性来初始化一些复杂的数据结构
模块的内部可以通过使用isMainModule内置变量来判断当前模块是否为主模块
来看看下面两个模块的代码:
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() # Module B |
1 2 3 4 5 6 7 | 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 = x + 1 |
模块的符号的书写要符合module.symbol的语法
如果一个符号在两个模块中都定义过了
而且第三个模块引用了这两个模块
来看看下面三个模块的代码:
1 2 | # Module A var x * : string |
1 2 | # Module B var x * : int # Module C |
1 2 3 4 5 6 | 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 |
但这个规则并不适用于方法或迭代器
对于方法或迭代器来说,适用于重载的规则
来看看下面的代码:
1 2 3 4 5 6 7 8 9 | # 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? |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .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 接口并集成到在线客服系统