Nim教程【十四】
网友@沉没捕鱼,赞助了一台服务器
这个系列的教程写完之后,我们就要开始着手搭建Nim的社区了~
异常
Nim中的异常类型是对象类型
根据惯例,Nim中的异常类型的命名都应该以Error后缀结尾
在system模块中定义了异常类型的基类
所有的异常都应该派生自system.Exception类型
由于我们不清楚异常对象的生命周期,
所以必须在内存堆上为异常的实例分配空间
编译器不允许开发人员在栈上为异常分配空间
你如果想抛出一个异常,你必须为这个异常的msg属性赋值
按照约定,只有在非常特殊的情况下才应该引发异常
打个比方:你不应该为打不开一个文件而引发异常,
因为这个文件有可能是不存在的。
raise语句引发异常
你可以使用raise语句引发一个异常
请看下面的代码
1 2 3 4 5 | var e: ref OSError new(e) e.msg = "the request to the OS failed" raise e |
如果raise关键字后面美元后跟着一个异常的实例
那么将再次引发最后一个异常
system模块中还为我们定义了一个newException的方法
请看如下代码:(是不是简化了很多呢)
1 | raise newException(OSError, "the request to the OS failed" ) |
try语句捕获异常
可以用try语句捕获异常
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # read the first two lines of a text file that should contain numbers # and tries to add them var f: File if open (f, "numbers.txt" ): try : let a = readLine(f) let b = readLine(f) echo "sum: " , parseInt(a) + parseInt(b) except OverflowError: echo "overflow!" except ValueError: echo "could not convert string to integer" except IOError: echo "IO error!" except : echo "Unknown exception!" # reraise the unknown exception: raise finally : close(f) |
如果try代码块中的代码,执行的时候引发了一个异常
那么就会执行相应的except语句
如果后面的except语句没有明确列出这个异常
那么就会后自行最后一个空except语句
这看起来类似if else语句
如果存在finally语句,
那finally语句块内的代码无论如何都会被执行的
如果一个异常没有得到处理
那么这个异常会从堆栈向上传播
这就意味着,调用链上的方法有可能不会被执行
(如果他被执行了,那么他一定在一个finally子句中)
如果你需要访问异常对象
可以使用system模块中的getCurrentException方法或者getCurrentExceptionMsg方法
来看下面的示例代码
1 2 3 4 5 6 7 | try : doSomethingHere() except : let e = getCurrentException() msg = getCurrentExceptionMsg() echo "Got exception " , repr (e), " with message " , msg |
在方法上做关于异常的注解
如果你用{.raises.}对某一个方法进行了注解
那么在编译期就会检测这个方法(或这个方法所调用到的方法)会不会抛出了某个异常
如果会,则编译不通过
示例代码如下:
1 2 3 4 5 | proc complexProc() {.raises: [IOError, ArithmeticError].} = ... proc simpleProc() {.raises: [].} = ... |
这一段我也没怎么看明白,大家自己看原文吧先
泛型
Nim语言的方法参数化、迭代器、等特性都是靠语言本身的泛型特性实现的
这个特性对于强类型容器是非常有用的
来看一下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | type BinaryTreeObj[T] = object # BinaryTree is a generic type with # with generic param ``T`` le, ri: BinaryTree[T] # left and right subtrees; may be nil data: T # the data stored in a node BinaryTree * [T] = ref BinaryTreeObj[T] # type that is exported proc newNode * [T](data: T): BinaryTree[T] = # constructor for a node new(result) result.data = data proc add * [T](root: var BinaryTree[T], n: BinaryTree[T]) = # insert a node into the tree if root = = nil: root = n else : var it = root while it ! = nil: # compare the data items; uses the generic ``cmp`` proc # that works for any type that has a ``==`` and ``<`` operator var c = cmp (it.data, n.data) if c < 0 : if it.le = = nil: it.le = n return it = it.le else : if it.ri = = nil: it.ri = n return it = it.ri proc add * [T](root: var BinaryTree[T], data: T) = # convenience proc: add(root, newNode(data)) iterator preorder * [T](root: BinaryTree[T]): T = # Preorder traversal of a binary tree. # Since recursive iterators are not yet implemented, # this uses an explicit stack (which is more efficient anyway): var stack: seq[BinaryTree[T]] = @[root] while stack. len > 0 : var n = stack.pop() while n ! = nil: yield n.data add(stack, n.ri) # push right subtree onto the stack n = n.le # and follow the left pointer var root: BinaryTree[string] # instantiate a BinaryTree with ``string`` add(root, newNode( "hello" )) # instantiates ``newNode`` and ``add`` add(root, "world" ) # instantiates the second ``add`` proc for str in preorder(root): stdout.writeln( str ) |
上面的示例展示了一个泛型二叉树
通过这个例子,您可以看到,可以用方括号来完成方法的泛型化、泛型迭代器等特性
【推荐】国内首个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 接口并集成到在线客服系统