bindSym

上面的 debug 宏依赖于这样一个事实,write、writeLine 和 stdout 是在 system 模块中声明的,所以在实例化时的上下文里是可见的。有一种使用绑定标识符 (即 symbols) 代替未绑定的标识符的方法,这用到了内置的 bindSym:

  1. import std/macros
  2. macro debug(n: varargs[typed]): untyped =
  3. result = newNimNode(nnkStmtList, n)
  4. for x in n:
  5. # 我们通过 'bindSym' 在作用域中绑定符号:
  6. add(result, newCall(bindSym"write", bindSym"stdout", toStrLit(x)))
  7. add(result, newCall(bindSym"write", bindSym"stdout", newStrLitNode(": ")))
  8. add(result, newCall(bindSym"writeLine", bindSym"stdout", x))
  9. var
  10. a: array[0..10, int]
  11. x = "some string"
  12. a[0] = 42
  13. a[1] = 45
  14. debug(a[0], a[1], x)

这个宏展开为以下代码:

  1. write(stdout, "a[0]")
  2. write(stdout, ": ")
  3. writeLine(stdout, a[0])
  4. write(stdout, "a[1]")
  5. write(stdout, ": ")
  6. writeLine(stdout, a[1])
  7. write(stdout, "x")
  8. write(stdout, ": ")
  9. writeLine(stdout, x)

在这个版本的 debug 中,标识符 write `, `writeLine 和 stdout 已经绑定,不会重复查找。 如示例所示, bindSym 确切可以隐式处理重载标识符。

注意,传递给 bindSym 的标识符名称必须是常量。实验性功能 dynamicBindSym (实验手册)允许动态地计算这个值。