2011-05-29 26 views
4

我猜标题说了。我正在读一本书,我可以看到它们是如何工作的,但为什么我会用普通参数创建它们而不是常规方法?我不明白Ruby Proc的背后......为什么不使用普通的方法?

我搜索了Google,所以我更加困惑。

请说明。谢谢。

+0

如果您可以使用Proc展示“本书”的示例,并且您展示了如何使用普通方法完成该示例,那么这个问题会更好。另外,不要说“我在读书”,你可能希望指定哪本书。 – 2011-05-30 00:08:10

回答

6

一个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有很多创意方法。

1

Procs - 只是延迟调用的'方法'。你可以在proc中保存一些代码,然后再执行它。很难解释你可以在哪里使用它们,我会尝试从我的项目中获得例子。

+0

请解释“延迟致电”。我可以随时在我的程序中调用方法。这不是一个“延迟呼叫”吗? – emurad 2011-05-29 12:11:57

+0

当你写这样的事情:a = Proc.new {puts'Hello world'}它现在不被执行,但是当你执行一次调用时它会被执行 – bor1s 2011-05-29 12:13:27

+0

想象一下,你需要将这个'a'传递给执行另一种方法,所以你可以这样做:some_method(a)和内部调用a.call来执行 – bor1s 2011-05-29 12:15:21

2

Procs可以作为对象传递并在需要时调用。这对模块化(除其他外)和延迟处理很有用。一个例子是ActiveRecord允许Procs进行验证的方式。一些例子:

validates_presence_of :admin_password, :if => Proc.new{|u| u.admin?} 

在这种情况下,无论何时执行验证,都会调用Proc(并重用)。

1

方法是具体的,你必须知道如何调用。 Procs和块是任意单位的代码,可以传递和随意使用。我想你可以把Proc看作是一种封闭。

当您的方法需要Proc中存储的任何代码的帮助时,您使用Proc。也许有些逻辑从某处加载资源,或者其他不重要的东西。与块不同,Procs旨在保留在变量中。

1

好问题,回答完这个问题后,你会清楚地知道在哪里以及如何使用Proc。 我的理解是,Proc的优点是可以将Proc作为参数传递给另一个方法。当你定义通常的方法时,它绑定到当前的上下文并且不能改变,你不能将这个方法传递给另一个地方。但是用Proc你可以做到这一点。所有迭代器都使用这个魔法。你只是说说如何处理数组中的每个项目(你创建了proc对象)并传递给迭代器,然后迭代器将此方法作为一个对象并在其功能中深入执行。

1

另一个常用的用法是简化结构为解释器的东西。假设你有某种形式的计算器,你可以做这样的(分开运营商和它的定义之间的关联):

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) 

后一种方法也使得特殊情况下脱颖而出(恕我直言)

一旦您习惯了这种方法,可以将数量惊人的事物构造为自定义数据结构的解释器。

相关问题