向模板传代码块

您可以在特殊的 : 语法之后将一个语句块作为最后一个参数传递给模板:

  1. template withFile(f, fn, mode, actions: untyped): untyped =
  2. var f: File
  3. if open(f, fn, mode):
  4. try:
  5. actions
  6. finally:
  7. close(f)
  8. else:
  9. quit("cannot open: " & fn)
  10.  
  11. withFile(txt, "ttempl3.txt", fmWrite): # 特殊冒号
  12. txt.writeLine("line 1")
  13. txt.writeLine("line 2")

在这个例子中,两个 writeLine 语句绑定到 actions 参数。

通常将一块代码传递给模板,接受块的参数需要是“untyped”类型。 因为符号查找会延迟到模板实例化时间:

  1. template t(body: typed) =
  2. block:
  3. body
  4.  
  5. t:
  6. var i = 1
  7. echo i
  8.  
  9. t:
  10. var i = 2 # '尝试重新声明i'失败
  11. echo i

上面的代码因已经声明了 i 的错误信息失败。 原因是 var i = … 需要在传递给 body 参数之前进行类型检查,而Nim中的类型检查意味着符号查找。 为了使符号查找成功,需要将 i 添加到当前(即外部)范围。 在类型检查之后,这些对符号表的添加不会回滚(无论好坏)。 同样的代码可以用 untyped ,因为传递的主体不需要进行类型检查:

  1. template t(body: untyped) =
  2. block:
  3. body
  4.  
  5. t:
  6. var i = 1
  7. echo i
  8.  
  9. t:
  10. var i = 2 # 编译
  11. echo i