For 循环宏
当宏只有一个输入参数,而且这个参数的类型是特殊的 system.ForLoopStmt 时, 这个宏可以重写整个 for 循环:
import std/macros
macro example(loop: ForLoopStmt) =
result = newTree(nnkForStmt) # 创建一个新的 For 循环。
result.add loop[^3] # 这是 "item" 。
result.add loop[^2][^1] # 这是 "[1, 2, 3]" 。
result.add newCall(bindSym"echo", loop[0])
for item in example([1, 2, 3]): discard
展开为:
for item in items([1, 2, 3]):
echo item
再举一个例子:
import std/macros
macro enumerate(x: ForLoopStmt): untyped =
expectKind x, nnkForStmt
# 检查是否指定了计数的起始值
var countStart = if x[^2].len == 2: newLit(0) else: x[^2][1]
result = newStmtList()
# 我们把第一个 for 循环变量修改为整数计数器:
result.add newVarStmt(x[0], countStart)
var body = x[^1]
if body.kind != nnkStmtList:
body = newTree(nnkStmtList, body)
body.add newCall(bindSym"inc", x[0])
var newFor = newTree(nnkForStmt)
for i in 1..x.len-3:
newFor.add x[i]
# 将 enumerate(X) 转换为 'X'
newFor.add x[^2][^1]
newFor.add body
result.add newFor
# 现在将整个宏包装到代码块里从而创建一个新的作用域
result = quote do:
block: `result`
for a, b in enumerate(items([1, 2, 3])):
echo a, " ", b
# 如果不将宏包装到代码块里,我们就需要为这里的 `a` 和 `b` 选择不同的名称
# 以免犯重复定义的错误。
for a, b in enumerate(10, [1, 2, 3, 5]):
echo a, " ", b
当前内容版权归 vectorworkshopbaoerjie 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 vectorworkshopbaoerjie .