Ruby has amzing object/Proc objects. let's how we can use them in our programming.
>> #Lets study the block and procs in the details
>>           
>> # 1. pass, block, proc as an argument to the funcion
>> def test_proc a
 |   a.call if a
 | end  
=> :test_proc
>> #passing a proc to the function
>> test_proc -
 | 
 | ;
SyntaxError: unexpected ';'
>> test_proc ->{p "Hey tell me this : #{self}"}
"Hey tell me this : main"
=> "Hey tell me this : main"
>> # This worked as expected as we passed proc/lambda to the function

>> #Now try with block
>> test_proc {p "Hey tell me this : #{self}"}
ArgumentError: wrong number of arguments (0 for 1)
from (pry):23:in `test_proc'
>> #Yeah, thats correct we havn't send any prameter(value or object)
>> 
>> #How to access a block in function ??? There are two ways 1. convert it to the porc itself
>> # 2. use yield to call for a passed block in ruby 
>> # Now, try method 1 for the block
>> def test_proc &block
 |   p block.class
 |   block.call
 | end  
=> :test_proc
>> test_proc {p "Hey tell me this : #{self}"}
Proc
"Hey tell me this : main"
=> "Hey tell me this : main"
>> # Note '&' changes a block to proc, we have printed 'block.class' and that truned to be a proc
>> 
>> #Note: but this is not an ideal case we can't be sure if need to send block everytime. For this we have a weapon called 'yield'
>> #Using 'yield'
>>  
>> def test_proc 
 |   yield if block_given? #call if block is passed to the function
 | end  
=> :test_proc
>> test_proc {p "Hey tell me this : #{self}"}
"Hey tell me this : main"
=> "Hey tell me this : main"


>>