Nim中如何使迭代变量在匿名函数中按值捕获而非引用?
Nim中如何使迭代变量在匿名函数中按值捕获而非引用?
你观察得很准确!Nim里循环迭代变量在闭包中确实是按引用捕获的,就像Python、Ruby这些语言一样,所以所有匿名函数最后都指向同一个i变量,循环结束后i的值停在5,调用时自然全输出5。
要解决这个问题,核心思路是为每个迭代创建一个独立的局部变量,让闭包捕获这个变量的副本,具体有两种常用方式:
方法一:循环内创建局部变量保存当前值
在每次迭代里,把i的值赋值给一个新的局部变量,闭包捕获这个局部变量即可:
var functions: seq[proc(): int] = @[] functions.add(proc(): int = 233) for i in 1 .. 5: let current_i = i # 用局部变量保存当前迭代的i值 functions.add(proc(): int = current_i) for i in 1 .. 5: echo functions[i]()
运行这段代码,输出就会是1、2、3、4、5,每个闭包都绑定了对应迭代的current_i值。
方法二:利用块作用域隔离变量
可以用block语句创建独立的作用域,在块内定义变量来保存i的值,同样能让每个闭包捕获独立的变量:
var functions: seq[proc(): int] = @[] functions.add(proc(): int = 233) for i in 1 .. 5: block: let val = i functions.add(proc(): int = val) for i in 1 .. 5: echo functions[i]()
这个方法的原理和第一种完全一致,只是用块作用域来明确划分每个变量的生命周期,让代码结构更清晰。
简单来说,循环的迭代变量i是全局于整个循环的单一变量,每次迭代只是更新它的值;而我们创建的局部变量在每次迭代中都是全新的实例,闭包捕获这些实例后,就能保留对应迭代的具体值啦。
备注:内容来源于stack exchange,提问作者init 1
相关产品推荐
相关产品推荐

