Ruby scope returning Proc from function

Based on the JavaScript background, I'm used to being able to use the dynamic JavaScript region to encapsulate values โ€‹โ€‹in a function. For instance:

function Dog( firstname, lastname ) { this.fullname = firstname + lastname return { say_name: function () { return fullname; } } } 

Now in Ruby, I'm not sure that something like this will work too well:

 class Foo attr_accessor :bar, :baz def initialize bar, baz @bar = bar @baz = baz end def give_me_a_proc return Proc.new { @bar + @baz } end end 

Can someone give a brief explanation of how scope works in Ruby? If I call Proc returned from give_me_a_proc , will it still have access to its time domain?

Also, are the values โ€‹โ€‹fixed after I define proc or will any changes made to Foo be transferred to Proc even after they are determined?

+4
source share
4 answers

In Ruby, proc is a closure. In Javascript, a function is a closure. The idea of โ€‹โ€‹closure is that it "closes" the environment in which it was defined. In Ruby, variables in proc can still be modified, even by code living outside proc, and new values โ€‹โ€‹will be reflected in proc (see Peakxu for a demonstration). Not sure if Javascript closes work this way.

+3
source

Yes, he will still have access to the time domain. See the documentation for the Proc class .

Changes are applied to the post-definition Proc. Irb results run with your class.

 > foo = Foo.new(1, 2) => #<Foo:0x007f9002167080 @bar=1, @baz=2> > quux = foo.give_me_a_proc => #<Proc: 0x007f900214f688@ (irb):11> > quux.call => 3 > foo.bar = 3 => 3 > quux.call => 5 
+3
source

Ruby procs and lambdas - closing. When you execute return Proc.new { @bar + @baz } , you really capture self , as a result of which instance variables are scanned. Ruby blocks are also a closure. Ruby allows you to modify variables, and the changes will propagate to the scope of the call, assuming that the scope of the call still exists:

 @hi = 0 def get_hi() lambda {@hi = 42} end get_hi.call() @hi #=> 42 

Note. If your proc does not have very weak arguments (it doesnโ€™t matter if it gets any arguments, how many, for example C int f(void) ), use lambda instead of Proc.new . lambda checks that you get the correct number of arguments.

+2
source

Ruby has a way to get closure from an object, it is very suitable for your example:

 class Foo # reopen Foo class def get_sum @bar + @baz end end m = Foo.new(5,20).method(:get_sum) m.call #=> 25 

m is a Method object and acts as a closure in an instance of Foo s, so instance variables and the value of self remain available.

+1
source

All Articles