我正在尝试用Ruby编写一个闭包。这是用Python编写的代码:
def counter():
x = 0
def increment(y):
nonlocal x
x += y
print(x)
return increment
Ruby中是否存在“非本地”等效项,因此我可以从内部增量中访问并更改变量x?
答案 0 :(得分:2)
可能是这样的:
class CGroup
def counter
@x ||= 0
lambda do |y|
@x += y
end
end
end
然后:
group = CGroup.new
c = group.counter
c.call(1)
=> 1
c.call(1)
=> 2
我不知道Python nonlocal
的直接模拟。
编辑:实例变量是不必要的,并且使用方法的本地变量可以实现相同的功能。这使得该类变得多余,尽管Ruby中的很多内容都发生在对象的上下文中。
答案 1 :(得分:2)
由于反对使用对象,为什么不使用lambda?
counter_generator = ->(){
x ||= 0
->(y){
x += y
puts x
}
}
i = counter_generator.call
=> #<Proc:0x00000100867508@(irb):17 (lambda)>
i.call(1)
1
=> nil
i.call(1)
2
=> nil
请注意,incrementor实际上返回nil,因为你只指定输出x的值,而不是返回它。
答案 2 :(得分:2)
nonlocal
关键字告诉Python要捕获哪些变量。在Ruby中,您不需要这样的关键字:除非另有明确说明,否则将捕获所有变量。
因此,与Python代码相当的Ruby几乎可以直接翻译:
counter = -> {
x = 0
->y {
x += y
puts x
}
}
i = counter.()
i.(2)
# 2
i.(3)
# 5
使用counter
的方法可能更为惯用,但是:
def counter
x = 0
->y {
x += y
puts x
}
end
i = counter
i.(2)
# 2
i.(3)
# 5