A process is different from another because you can save it in a variable. Therefore, you can pass it as a parameter to a function, return it from a function, manipulate it, etc.
Procs, lambdas, and blocks are one of the main things that make Ruby flawless. They, for example, underlie Ruby iterators. When you do something like:
collection.each do |item|
you basically pass a block (Proc object) for each function.
Let's say you have many arrays that you want to process the same way. So that you cannot write every code every time, you can do something like:
handler = Proc.new{|item| do_something_with(item)} array1.each &handler array2.each &handler .... arrayn.each &handler
If you want to pass Proc to a function as a block, you must execute it with & . The same thing happens if you define a function that takes a block parameter.
Another useful way to use Proc is through functions.
Say that you have a function that instantiates an object, makes some minor changes, and returns it. To make it more flexible, you can force it to accept such a block:
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
The way out is where the magic happens. When this line is evaluated, the function will execute the block that you specify using my_item as a parameter. This way you can do things like:
my_new_item = new_item(p1, p2) do |item| item.attribute3 = some_value end
Now my_new_item will have its own attribute3 set, as well as any other modification than in the block.
You do not use Procs and lambdas to replace functions, you use them to extend functions. You may have a function that returns a Proc that was built based on any parameters you give it. There are many ways to be creative with Procs.