简体   繁体   English

Ruby等效于python nonlocal

[英]Ruby equivalent of python nonlocal

I am trying to write a closure in Ruby. 我试图用Ruby编写闭包。 This is the code written in Python: 这是用Python编写的代码:

def counter():
    x = 0
    def increment(y):
        nonlocal x
        x += y
        print(x)
    return increment

Is there a "nonlocal" equivalent in Ruby so I can access and make changes to the variable x from inside increment? Ruby中是否有一个“非本地”等效项,因此我可以从增量中访问变量x并对其进行更改?

Maybe something like: 也许像这样:

class CGroup
  def counter
    @x ||= 0
    lambda do |y|
      @x += y
    end
  end
end

Then: 然后:

group = CGroup.new
c = group.counter
c.call(1)
=> 1
c.call(1)
=> 2

I'm not aware of a direct analog for Python's nonlocal . 我不知道Python的nonlocal的直接模拟。

EDIT : The instance variable is unnecessary, and the same thing can be achieved with a variable local to the method. 编辑 :实例变量是不必要的,并且可以使用方法本地的变量来实现相同的目的。 This makes the class superfluous, although much in Ruby takes place within the context of an object. 这使得该类成为多余的,尽管Ruby中的很多事情都是在对象的上下文中发生的。

Since there is objection to using an object, why not just use a lambda? 由于有人反对使用对象,为什么不只使用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

Note that the incrementor actually returns nil because you've only specified to output the value of x, not to return it. 注意,增量器实际上返回nil,因为您仅指定输出x的值,而不返回它。

The nonlocal keyword tells Python which variables to capture. nonlocal关键字告诉Python要捕获哪些变量。 In Ruby, you don't need such a keyword: all variables are captured unless explicitly mentioned otherwise. 在Ruby中,您不需要这样的关键字:除非另有明确说明,否则将捕获所有变量。

So, the Ruby equivalent to your Python code translates almost directly: 因此,相当于Python代码的Ruby几乎可以直接转换:

counter = -> {
  x = 0
  ->y {
    x += y
    puts x
  }
}

i = counter.()

i.(2)
# 2

i.(3)
# 5

It would probably be more idiomatic to use a method for counter , though: 不过,使用counter方法可能会更惯用:

def counter
  x = 0
  ->y {
    x += y
    puts x
  }
end

i = counter

i.(2)
# 2

i.(3)
# 5

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM