Ruby scope,从函数返回一个Proc
来自JavaScript后台我已经习惯于能够使用JavaScript的动态范围来封装函数中的值。例如:Ruby scope,从函数返回一个Proc
function Dog(firstname, lastname) {
this.fullname = firstname + lastname
return {
say_name: function() {
return fullname;
}
}
}
现在在Ruby中,我不那么肯定会有这样的工作也很好:
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
谁能给的范围在Ruby中是如何工作的一个快速的解释?如果我打电话给从give_me_a_proc
返回的Proc,它是否仍然可以访问其定义范围?
同样,一旦我定义了proc,或者做了任何在Foo
中做出的更改,即使在定义之后,这些值也会被固定下来。
在Ruby中,一个proc是一个闭包。在Javascript中,函数是闭包。关闭的想法是它“关闭”了它所定义的环境。在Ruby中,proc中的变量仍然可以改变,即使代码处于proc之外,新值也会反映在proc中(参见peakxu的演示)。不确定Javascript关闭是否以这种方式工作。
是的,它仍然可以访问定义时间范围。见documentation for Proc class。
更改进行到Proc后定义。 irb的结果与你的班级一起运行。
> foo = Foo.new(1, 2)
=> #<Foo:0x007f9002167080 @bar=1, @baz=2>
> quux = foo.give_me_a_proc
=> #<Proc:[email protected](irb):11>
> quux.call
=> 3
> foo.bar = 3
=> 3
> quux.call
=> 5
Ruby procs和lambdas是关闭。当你做return Proc.new { @bar + @baz }
你真的捕获了self
,这是实例变量的查找方式。 Ruby块也是闭包。红宝石不会让你改变的变量和更改将传播到呼叫范围,假设呼叫范围内仍然存在:
@hi = 0
def get_hi()
lambda {@hi = 42}
end
get_hi.call()
@hi #=> 42
注意:除非你的PROC具有非常宽松的参数要求(不介意它得到任何参数,有多少种,像C的int f(void)
),使用lambda
而不是Proc.new
。 lambda
检查以确保您获得正确数量的参数。
Ruby有一个方法来获得从对象关闭,它适合很高兴你的例子:
class Foo
# reopen Foo class
def get_sum
@bar + @baz
end
end
m = Foo.new(5,20).method(:get_sum)
m.call #=> 25
的m
是Method
对象,并将其作为在Foo
的实例关闭,所以实例变量并且self
的值仍然可用。
谢谢,这正是我正在寻找的那种解释 – 2012-07-20 16:55:01
欢迎。感谢您的反馈。你扔掉这些东西,你想知道它是否达到了标准。 :) – seph 2012-07-20 22:35:09