zoukankan      html  css  js  c++  java
  • Nim教程【十一】

    引用类型和指针类型

    不同的引用可以只想和修改相同的内存单元

    在nim中有两种引用方式,一种是追踪引用,另一种是非追踪引用

    非追踪引用也就是指针,指向手动在内存中分配的对象;

    追踪引用指向一个垃圾收集的对象;

    非追踪引用是不安全的

    然而对于一些低级操作(比如说访问硬件),非追踪引用是不可避免的

    追踪引用用ref关键词声明

    非追踪引用用ptr关键词声明

    可以用[]来解包一个引用(访问一个元组或对象域时要用到)

    请看下面的代码:

    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

    来看一下下面的代码

    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语句导入另一个模块的符号

    在一个模块中,只有用星号标记的符号,才能导出给另一个模块

    来看看下面的代码:

    # 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内置变量来判断当前模块是否为主模块

    来看看下面两个模块的代码:

    # 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.
    
    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的语法

    如果一个符号在两个模块中都定义过了

    而且第三个模块引用了这两个模块

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

    # 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?
  • 相关阅读:
    cocos2d-x的初步学习七
    cocos2d-x的初步学习六
    cocos2d-x的初步学习五
    cocos2d-x的初步学习四
    net core or Linux
    XML序列化反序列化
    用NSoup解析HTML
    ubuntu 下的ftp安装及root身份远程配置
    Windows 10 子系统Linux重启(不重启Win10)
    C# HttpRequest 请求
  • 原文地址:https://www.cnblogs.com/liulun/p/4579946.html
Copyright © 2011-2022 走看看