我在库中没有创建的类中有一个讨厌的小函数问题(因此无法编辑)。这是一个简单的类,其中包含恼人的行为:
class Foo # This is a class I cannot
def setmyproc(&code) # safely edit.
@prc = Proc.new # Due to it being in a
end # frustratingly complex
def callmyproc() # hierarchy, I don't
@prc.call # even know how to reopen
end # it. Consider this class
end # set in stone.
当我尝试迭代并生成这些对象的数组时遇到问题。我期望用每个对象将一个不同的值替换为Proc i
,但相反的是变量i
在它们之间共享。
$bar = []
for i in (0..15)
$bar[i] = Foo.new
$bar[i].setmyproc { puts i }
end
$bar[3].callmyproc # expected to print 3
$bar[6].callmyproc # expected to print 6
输出
15 15
我可以在循环内做什么来为每个对象保留i
的单独值?
答案 0 :(得分:3)
使用此:
$bar = []
(0..15).each do |i|
$bar[i] = Foo.new
$bar[i].setmyproc { puts i }
end
$bar[3].callmyproc # prints 3
$bar[6].callmyproc # prints 6
如果您确实需要在循环内部进行更改,请使用此选项(仅限ruby 1.9):
$bar = []
for i in (0..15)
->(x) do
$bar[x] = Foo.new
$bar[x].setmyproc { puts x }
end.(i)
end
$bar[3].callmyproc # prints 3
$bar[6].callmyproc # prints 6
答案 1 :(得分:2)
传递到$ bar数组中每个Foo的块绑定到同一个变量i
。无论何时发送callmyproc
,都会使用原始范围中i
的当前值。
$bar[3].callmyproc
=> 15
$bar[6].callmyproc
=> 15
i = 42
$bar[3].callmyproc
=> 42
$bar[6].callmyproc
=> 42
您需要在每个过程中发送一个不同的对象:
0.upto(15) do |i|
$bar[i] = Foo.new
$bar[i].setmyproc { i.to_i }
end
$bar[3].callmyproc
=> 3
$bar[6].callmyproc
=> 6
答案 2 :(得分:1)
好的,首先,欢迎关闭:)
闭包是一段代码,你可以像变量一样传递,这是一个简单的部分。另一方面是闭包保持了调用它的范围。
实际发生的是,当你存储你的触发器时,每个触发器都会引用n。即使你超出了for循环的范围,对n的引用仍然存在,每次执行你的proc时,它们都会打印出n的最终值。这里的问题是每次迭代都不在自己的范围内。
Adrian建议做的是将for循环换成range.each块。不同之处在于每个迭代都有自己的范围,这就是与proc
绑定的内容$bar = []
(0..15).each do |i|
#each i in here is local for this block
$bar[i] = Foo.new
$bar[i].setmyproc { puts i }
end
这真的不是一件简单的事情,但它是其中一个会让你绊倒的东西,直到你真正得到它为止。我可能做了很糟糕的解释,如果它不凝胶我会花一点时间谷歌搜索闭包如何与范围一起工作。