Ruby equivalent of non-local python

I am trying to write closure in Ruby. This is the code written in 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 the internal increment?

+6
source share
3 answers

The nonlocal tells Python which variables to capture. In Ruby, you don't need a keyword like this: all variables are captured unless explicitly stated otherwise.

So, the Ruby equivalent for your Python code translates almost directly:

 counter = -> { x = 0 ->y { x += y puts x } } i = counter.() i.(2) # 2 i.(3) # 5 

It would probably be more idiomatic to use the method for counter , though:

 def counter x = 0 ->y { x += y puts x } end i = counter i.(2) # 2 i.(3) # 5 
+2
source

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 do not know a direct analogue for Python nonlocal .

EDIT : an instance variable is not needed, and the same thing can be achieved with a variable local to the method. This makes the class redundant, although much in Ruby happens in the context of the object.

+2
source

Since there is an objection to using an object, why not just use 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 specified only the value to output x, and not return it.

+2
source

All Articles