I do not understand the idea of ​​Ruby Proc ... why not just use the regular method?

I think the name says it. I am reading a book and I see how they work, but why should I create them instead of the usual methods with normal parameters?

I searched google and I just got a little confused.

Please clarify. Thanks.

+4
source share
6 answers

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| //process item end 

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.

+6
source

Procs can be passed as objects and called if necessary. This is useful for modularity (among other things) and delayed processing. An example is the way that ActiveRecord allows Procs to validate. Some examples:

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

In this case, Proc is called (and reused) whenever a validation is performed.

+2
source

Procs are simply call-delayed “methods”. You can save some code in proc and then execute it later. It is hard to explain where you can use them. I will try to give an example from my projects.

+1
source

A method is something specific that you need to know how to call. Procs and blocks are arbitrary units of code that can be transmitted and used on demand. I think you can think of Proc as closing.

You use Proc when your method needs help from any code stored in Proc. Maybe some logic to load the resource from somewhere or something else is not trivial. Unlike a block, Procs are designed to be stored in a variable.

+1
source

Good question, by answering this question, you will clearly know where and how to use Proc. As far as I understand, the advantage of Proc is that you can pass the parameter Proc as to other methods. When you define a regular method, it is bound to the current context and cannot be changed; you cannot transfer this method to other places. But with Proc you can do it. All iterators use this magic. You just say what to do with each element of the array (you created the proc object) and go to the iterator, and then the iterator takes this method as an object and executes deep inside its functionality.

+1
source

Another common use is to simplify things that are structured like translators. Suppose you have some kind of calculator, you can do it like this (which shares the connection between the operator and its definition):

 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 

Or you can use lambda to make it much cleaner and denser (i.e. pull the operator and its definition together to make it obvious what is happening):

 ops = { '+' => lambda { |a, b| a + b }, '-' => lambda { |a, b| a - b }, #... } raise 'Unknown operator' if(!ops.has_key?(op)) ops[op].call(a, b) 

The latter approach also makes special cases more meaningful (IMHO).

An amazing amount of things can be structured as interpreters of custom data structures as soon as you get used to this approach.

+1
source

All Articles