zoukankan      html  css  js  c++  java
  • Nim教程【十五】【完结】

    模版

    模版是Nim语言中的抽象语法树,它是一种简单的替换机制,在编译期被处理

    这个特性使Nim语言可以和C语言很好的运行在一起

    像调用一个方法一样调用一个模版

    请看如下代码:

    template `!=` (a, b: expr): expr =
      # this definition exists in the System module
      not (a == b)
    
    assert(5 != 6) # the compiler rewrites that to: assert(not (5 == 6))

    类似下面这些符号,其实都是模版

    =,>,>=,in,notin

    这一个好处,如果你重载==操作符,

    !=运算符也就自动提供出来了

    并可以做正确的事!

    A>B被变换到b<a。 b in a被变换成含有(b,a)。 notin和IsNot运算有明显的意义。

    模板为懒人提供了很大帮助。考虑一个简单的PROC进行日志记录:

    const
      debug = true
    
    proc log(msg: string) {.inline.} =
      if debug: stdout.writeln(msg)
    
    var
      x = 4
    log("x has the value: " & $x)

    这段代码有个缺点,如果有一天把debug变量设置为了false

    那么&操作和$操作还是会执行的,而这些操作的资源消耗是非常大的。

    (调用方法的时候,会先执行方法参数位置处的表达式)

    这个时候就可以考虑用模版来解决这个问题:

    const
      debug = true
    
    template log(msg: string) =
      if debug: stdout.writeln(msg)
    
    var
      x = 4
    log("x has the value: " & $x)

    模版的参数类型可以是普通的类型,也可以是表达式;

    template withFile(f: expr, filename: string, mode: FileMode,
                      body: stmt): stmt {.immediate.} =
      let fn = filename
      var f: File
      if open(f, fn, mode):
        try:
          body
        finally:
          close(f)
      else:
        quit("cannot open: " & fn)
    
    withFile(txt, "ttempl3.txt", fmWrite):
      txt.writeln("line 1")
      txt.writeln("line 2")

    在这个例子中,两个writeln语句绑定到的是body参数

    这段代码可以帮助开发人员避免“忘记关闭文件”的错误

    Nim语言的宏提供了一个高级的编译期的替换功能

    Nim语言的宏不能替换语言本身的语法,

    但这并不是什么缺憾,因为Nim语言本身已经足够灵活了。

    如果外部接口在编译期不可用,那么你就必须用纯Nim语言写宏

    (这估计就是在说Nim和C混合编程的时候要注意的事情)

    你可以使用Nim代码编写任何形式的宏,编译器会在编译期把他们翻译成真正的Nim代码。

    可以有两种办法写一个宏

    用Nim代码编写宏,让编译器解析它

    手动创建抽象语法树AST,你告诉编译器

    如果你想建立抽象语法树AST,那么你一定要知道Nim语言的语法是怎么转换为抽象语法树的

    在N关于宏的帮助说明文档,你可以找到关于AST的帮助说明

    你一旦写了一个宏,

    那么你有两种办法可以使用这个宏

    像调用一个方法一样调用一个宏

    通过一种特殊的语法调用宏(macrostmt声明宏)

    表达式宏

    下面的代码实现了一个可变参数数量的宏

    # to work with Nim syntax trees, we need an API that is defined in the
    # ``macros`` module:
    import macros
    
    macro debug(n: varargs[expr]): stmt =
      # `n` is a Nim AST that contains a list of expressions;
      # this macro returns a list of statements:
      result = newNimNode(nnkStmtList, n)
      # iterate over any argument that is passed to this macro:
      for i in 0..n.len-1:
        # add a call to the statement list that writes the expression;
        # `toStrLit` converts an AST to its string representation:
        result.add(newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
        # add a call to the statement list that writes ": "
        result.add(newCall("write", newIdentNode("stdout"), newStrLitNode(": ")))
        # add a call to the statement list that writes the expressions value:
        result.add(newCall("writeln", newIdentNode("stdout"), n[i]))
    
    var
      a: array[0..10, int]
      x = "some string"
    a[0] = 42
    a[1] = 45
    
    debug(a[0], a[1], x)

    编译完之后,最终展开的代码为:

    write(stdout, "a[0]")
    write(stdout, ": ")
    writeln(stdout, a[0])
    
    write(stdout, "a[1]")
    write(stdout, ": ")
    writeln(stdout, a[1])
    
    write(stdout, "x")
    write(stdout, ": ")
    writeln(stdout, x)

    声明宏

    声明宏在某种意义上就是表达式宏

    声明宏是用冒号表达式调用的

    下面的例子展示了正则表达式词法分析宏

    macro case_token(n: stmt): stmt =
      # creates a lexical analyzer from regular expressions
      # ... (implementation is an exercise for the reader :-)
      discard
    
    case_token: # this colon tells the parser it is a macro statement
    of r"[A-Za-z_]+[A-Za-z_0-9]*":
      return tkIdentifier
    of r"0-9+":
      return tkInteger
    of r"[+-*?]+":
      return tkOperator
    else:
      return tkUnknown

    后面还有个例子,不翻译了

    至此整个系列写完了

    喜欢的请点推荐

  • 相关阅读:
    sudo 做不到的事
    Oracle 用户操作表权限
    CentOS7.2 使用Shell安装Oracle12c
    package-cleanup
    glibc-commons 依赖解析 版本错误,xxx is duplicate yyy
    Centos7.2 编译安装方式搭建 phpMyAdmin
    Jenkins 环境搭建
    awk 使用案例
    Linux文件系统
    用python写一个计算器
  • 原文地址:https://www.cnblogs.com/liulun/p/4630234.html
Copyright © 2011-2022 走看看