For循环宏

一个宏作为唯一的输入参数,特殊类型 system.ForLoopStmt 的表达式可以重写整个 for 循环:

  1. import macros
  2. {.experimental: "forLoopMacros".}
  3.  
  4. macro enumerate(x: ForLoopStmt): untyped =
  5. expectKind x, nnkForStmt
  6. # 我们剥离第一个for循环变量并将其用作整数计数器:
  7. result = newStmtList()
  8. result.add newVarStmt(x[0], newLit(0))
  9. var body = x[^1]
  10. if body.kind != nnkStmtList:
  11. body = newTree(nnkStmtList, body)
  12. body.add newCall(bindSym"inc", x[0])
  13. var newFor = newTree(nnkForStmt)
  14. for i in 1..x.len-3:
  15. newFor.add x[i]
  16. # 将枚举(X)转换为'X'
  17. newFor.add x[^2][1]
  18. newFor.add body
  19. result.add newFor
  20. # 现在将整个宏包装在一个块中以创建一个新的作用域
  21. result = quote do:
  22. block: `result`
  23.  
  24. for a, b in enumerate(items([1, 2, 3])):
  25. echo a, " ", b
  26.  
  27. # 没有将宏包装在一个块中,我们需要在这里为 `a` 和 `b` 选择不同的名称以避免重定义错误
  28. for a, b in enumerate([1, 2, 3, 5]):
  29. echo a, " ", b

目前,必须通过 {.experimental: "forLoopMacros".} 显式启用循环宏。