我已经阅读了几本关于 Ruby 的书籍,并且了解如何创建和调用 Procs。但是这些书中的例子是做作的和琐碎的。我想知道什么时候使用 Proc 而不是使用传统方式来做同样的事情真正有用?也许有人可以发布一个重要的例子?
2 回答
在 Ruby 中,Proc是一种很好的方式来存储一些您希望稍后在对象中运行的代码。块不是对象,但它们可以很容易地转换为 Procs。Procs 对很多事情都很有用。Procs 通常用于实现回调。我最近在编写系统模拟时使用了 Procs。每次我step
在模拟中调用该方法时,我都希望发生各种事情。我不想让模拟对象本身知道那些事情的细节;我只是想让它调用我定义的回调。我可以通过定义一堆自定义类或对象来完成同样的事情,每个类或对象都有一个call
方法,但使用 Procs 肯定更简单。
class X
def initialize
@step_callbacks = []
end
def every_step(&proc)
# If you print proc.class here, you can see it is a Proc
@step_callbacks << proc
end
def step
# ...perform the step...
@step_callbacks.each do |proc|
proc.call
end
end
end
x = X.new
x.every_step do
# check some assertions about the state of the simulation
end
x.every_step do
# update a related simulation
end
x.step
x.step
我希望你不要认为这个例子是人为的。我确实用它来完成我的工作。此外,我使用相同的模式来处理我的 minecraft 机器人中收到的数据包,如您在此处看到的。
每当您想让某个对象调用某些代码但又不希望它确切知道它正在调用什么代码时,回调非常有用。Procs 是一种实现回调的简单方法。
Proc 是一个对象,因此您可以创建包含它们的复杂对象。例如,您可以创建将键与指令匹配的哈希:
object1 = {
:foo => ->{execute_foo_routine},
:bar => ->{execute_bar_routine},
...
}
...
object1[:foo].call # => execution
请注意,所有信息都包含在object1
. 当您想要封装所有必要的信息并使其独立于外部代码时,这很有用。object1
是便携式的。
如果您想使用方法来做到这一点,那么并非所有信息都可以放在对象中,但需要在其他地方定义方法:
object2 = {
:foo => :foo_routine,
:bar => :bar_routine,
...
}
def foo_routine
...
end
def bar_routine
...
end
...
send(object2[:foo]) # => execution
并且object2
不会像object1
.