我猜标题说了。我正在读一本书,我可以看到它们是如何工作的,但为什么我会用普通参数创建它们而不是常规方法?我不明白Ruby Proc的背后......为什么不使用普通的方法?
我搜索了Google,所以我更加困惑。
请说明。谢谢。
我猜标题说了。我正在读一本书,我可以看到它们是如何工作的,但为什么我会用普通参数创建它们而不是常规方法?我不明白Ruby Proc的背后......为什么不使用普通的方法?
我搜索了Google,所以我更加困惑。
请说明。谢谢。
一个proc是不同的,因为你可以将它存储在一个变量中。因此,您可以将它作为参数传递给函数,从函数返回,操纵它等。
过程,lambdas和块是使Ruby变得非常棒的主要事情之一。它们是Ruby的核心例如迭代器。当你做这样的事情:
collection.each do |item|
//process item
end
你基本上是通过一个块(一个Proc对象)到每个函数。
让我们说你一堆数组,你想以相同的方式处理。当你想传递一个Proc的功能块
handler = Proc.new{|item| do_something_with(item)}
array1.each &handler
array2.each &handler
....
arrayn.each &handler
,你有一个&
到preceed它:从编写每个代码每一次,你可以这样做拯救你。当你定义一个接受块参数的函数时也是如此。
使用Proc的另一个有用的方法是在函数中。假设你有一个函数来实例化一个对象,做一些小的修改并且返回它。为了使它更加灵活,你可以让它接受如下块:
def new_item(param1, param2, &block)
my_item = Item.new
my_item.attribute1 = param1
my_item.attribute2 = param2
yield my_item if block_given?\
return my_item
end
产量是魔术发生的地方。当该行被评估时,该函数将执行您以my_item作为参数提供的块。所以,你可以做的东西一样:比你在做块
my_new_item = new_item(p1, p2) do |item|
item.attribute3 = some_value
end
现在,my_new_item
将其attribute3
设置以及任何其他修改。
您不使用Procs和lambdas替换函数,而是使用它们来增强函数。 你可以有一个函数返回一个Proc,它是基于你给它的任何参数构建的。 Procs有很多创意方法。
Procs - 只是延迟调用的'方法'。你可以在proc中保存一些代码,然后再执行它。很难解释你可以在哪里使用它们,我会尝试从我的项目中获得例子。
Procs可以作为对象传递并在需要时调用。这对模块化(除其他外)和延迟处理很有用。一个例子是ActiveRecord允许Procs进行验证的方式。一些例子:
validates_presence_of :admin_password, :if => Proc.new{|u| u.admin?}
在这种情况下,无论何时执行验证,都会调用Proc(并重用)。
方法是具体的,你必须知道如何调用。 Procs和块是任意单位的代码,可以传递和随意使用。我想你可以把Proc看作是一种封闭。
当您的方法需要Proc中存储的任何代码的帮助时,您使用Proc。也许有些逻辑从某处加载资源,或者其他不重要的东西。与块不同,Procs旨在保留在变量中。
好问题,回答完这个问题后,你会清楚地知道在哪里以及如何使用Proc。 我的理解是,Proc的优点是可以将Proc作为参数传递给另一个方法。当你定义通常的方法时,它绑定到当前的上下文并且不能改变,你不能将这个方法传递给另一个地方。但是用Proc你可以做到这一点。所有迭代器都使用这个魔法。你只是说说如何处理数组中的每个项目(你创建了proc对象)并传递给迭代器,然后迭代器将此方法作为一个对象并在其功能中深入执行。
另一个常用的用法是简化结构为解释器的东西。假设你有某种形式的计算器,你可以做这样的(分开运营商和它的定义之间的关联):
def add(a, b); a + b; end
def sub(a, b); a - b; end
#...
if(op == '+')
add(a, b)
elsif(op == '-')
sub(a, b)
#...
else
raise 'Unknown operator'
end
或者你可以使用lambda表达式,使之变得更干净和更严格的(即拉动运营商和它的定义一起,使之明显是怎么回事):
ops = {
'+' => lambda { |a, b| a + b },
'-' => lambda { |a, b| a - b },
#...
}
raise 'Unknown operator' if(!ops.has_key?(op))
ops[op].call(a, b)
后一种方法也使得特殊情况下脱颖而出(恕我直言)
一旦您习惯了这种方法,可以将数量惊人的事物构造为自定义数据结构的解释器。
如果您可以使用Proc展示“本书”的示例,并且您展示了如何使用普通方法完成该示例,那么这个问题会更好。另外,不要说“我在读书”,你可能希望指定哪本书。 – 2011-05-30 00:08:10