Nim教程【十四】

时间:2022-10-16 11:27:14

网友@沉没捕鱼,赞助了一台服务器

这个系列的教程写完之后,我们就要开始着手搭建Nim的社区了~

异常

Nim中的异常类型是对象类型

根据惯例,Nim中的异常类型的命名都应该以Error后缀结尾

在system模块中定义了异常类型的基类

所有的异常都应该派生自system.Exception类型

由于我们不清楚异常对象的生命周期,

所以必须在内存堆上为异常的实例分配空间

编译器不允许开发人员在栈上为异常分配空间

你如果想抛出一个异常,你必须为这个异常的msg属性赋值

按照约定,只有在非常特殊的情况下才应该引发异常

打个比方:你不应该为打不开一个文件而引发异常,

因为这个文件有可能是不存在的。

raise语句引发异常

你可以使用raise语句引发一个异常

请看下面的代码

var
  e: ref OSError
new(e)
e.msg = "the request to the OS failed"
raise e

如果raise关键字后面美元后跟着一个异常的实例

那么将再次引发最后一个异常

system模块中还为我们定义了一个newException的方法

请看如下代码:(是不是简化了很多呢)

raise newException(OSError, "the request to the OS failed")

try语句捕获异常

可以用try语句捕获异常

# 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方法

来看下面的示例代码

try:
  doSomethingHere()
except:
  let
    e = getCurrentException()
    msg = getCurrentExceptionMsg()
  echo "Got exception ", repr(e), " with message ", msg

在方法上做关于异常的注解

如果你用{.raises.}对某一个方法进行了注解

那么在编译期就会检测这个方法(或这个方法所调用到的方法)会不会抛出了某个异常

如果会,则编译不通过

示例代码如下:

proc complexProc() {.raises: [IOError, ArithmeticError].} =
  ... proc simpleProc() {.raises: [].} =
  ...

这一段我也没怎么看明白,大家自己看原文吧先

泛型

Nim语言的方法参数化、迭代器、等特性都是靠语言本身的泛型特性实现的

这个特性对于强类型容器是非常有用的

来看一下代码

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)

上面的示例展示了一个泛型二叉树

通过这个例子,您可以看到,可以用方括号来完成方法的泛型化、泛型迭代器等特性

Nim教程【十四】的更多相关文章

  1. 无废话ExtJs 入门教程十四&lbrack;文本编辑器:Editor&rsqb;

    无废话ExtJs 入门教程十四[文本编辑器:Editor] extjs技术交流,欢迎加群(201926085) ExtJs自带的编辑器没有图片上传的功能,大部分时候能够满足我们的需要. 但有时候这个功 ...

  2. webpack4 系列教程&lpar;十四&rpar;:Clean Plugin and Watch Mode

    作者按:因为教程所示图片使用的是 github 仓库图片,网速过慢的朋友请移步<webpack4 系列教程(十四):Clean Plugin and Watch Mode>原文地址.更欢迎 ...

  3. RabbitMQ入门教程&lpar;十四&rpar;:RabbitMQ单机集群搭建

    原文:RabbitMQ入门教程(十四):RabbitMQ单机集群搭建 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://b ...

  4. WebGL简易教程&lpar;十四&rpar;:阴影

    目录 1. 概述 2. 示例 2.1. 着色器部分 2.1.1. 帧缓存着色器 2.1.2. 颜色缓存着色器 2.2. 绘制部分 2.2.1. 整体结构 2.2.2. 具体改动 3. 结果 4. 参考 ...

  5. Nim教程【四】

    这是国内第一个关于Nim的系列教程 先说废话 不得不说Rust也是门不错的语言,园子里 有人曾经说: Rust语言除了library或keyword缩写比较恶心以外其他所有地方完爆go 还有人曾这样评 ...

  6. 【转】机器学习教程 十四-利用tensorflow做手写数字识别

    模式识别领域应用机器学习的场景非常多,手写识别就是其中一种,最简单的数字识别是一个多类分类问题,我们借这个多类分类问题来介绍一下google最新开源的tensorflow框架,后面深度学习的内容都会基 ...

  7. Redis教程&lpar;十四&rpar;:内存优化介绍

    转载于:http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/142.html 一.特殊编码: 自从Redis 2.2之后,很多数据类型都 ...

  8. Unity3D脚本中文系列教程&lpar;十四&rpar;

    http://dong2008hong.blog.163.com/blog/static/469688272014032134394/ WWWFrom 类Unity3D脚本中文系列教程(十三)辅助类. ...

  9. Spring Boot2 系列教程 &lpar;十四&rpar; &vert; 统一异常处理

    如题,今天介绍 SpringBoot 是如何统一处理全局异常的.SpringBoot 中的全局异常处理主要起作用的两个注解是 @ControllerAdvice 和 @ExceptionHandler ...

  10. Wix 安装部署教程&lpar;十四&rpar; -- 多语言安装包之用户许可协议

    在上一篇中,留下了许可协议的问题,目前已经解决.感谢网友武全的指点! 问题 一般我们是用WixVariable 来设定许可协议.如下所示: <WixVariable Id="WixUI ...

随机推荐

  1. Oracle 和 SqlServer 的区别

    --sql server 与  oracle的区别: --DBMS 数据库管理系统--1.数据类型不同.      --sql server 的数据类型:int ,smallint ,char,var ...

  2. 开发者调试工具Chrome Workspace

    Workspace是个什么样的东西呢?他能够在开发者工具中调试修改js或者css同时自动保存文件,能够避免开发人员在工具中调试好,再到编辑器中修改一次代码的重复操作,能够提高一定的效率 配置Chrom ...

  3. 【unity3d游戏开发脚本笔记之一:坐标系选择对物体运动的影响】

    时间:2016年9月24日17:38:21   作者:yexiaopeng 博客园     在unity3d的世界中,其坐标系可分为四种,世界坐标系-WorldSpace   本地坐标系-LocalS ...

  4. if

    语句快中的变量与函数的局部变量关系;

  5. sqlserver 操作xml

    1.xml.exist    输入为XQuery表达式,返回0,1或是Null.0表示不存在,1表示存在,Null表示输入为空 2.xml.value    输入为XQuery表达式,返回一个SQL ...

  6. 关于getchar&lpar;&rpar;的知识

    char* s1 = "123",字符串"123"这段内存是只读的,就是说其内容不能改变///char *s 这个是指申请一个地址空间 记录一个地址 #incl ...

  7. JavaScript中数组Array方法详解

    ECMAScript 3在Array.prototype中定义了一些很有用的操作数组的函数,这意味着这些函数作为任何数组的方法都是可用的. 1.Array.join()方法 Array.join()方 ...

  8. JPA的一对多映射&lpar;双向&rpar;关联

    实体Customer:用户. 实体Order:订单. Customer和Order是一对多关系.那么在JPA中,如何表示一对多的双向关联呢? JPA使用@OneToMany和@ManyToOne来标识 ...

  9. Java压测之四两拨千斤

    压测之四两拨千斤核心观念: 1.传统的http请求肯定不能用于压测,原因是请求一次,响应一次,而响应数据同时占用了客户端的带宽,故此,客户端请求后,不需要接受响应,让服务器单相思去. 2.寻找可以令服 ...

  10. Light OJ 1148

    题意: 给你N 个人, 每个人说出有多少人和他一队, 不包括他自己, 输出总人数最少值 思路: 排个序, 按照给的数目把人分为一组,就可以得出最少人数 #include<bits/stdc++. ...