Week 2, Day 6, Block-Proc-Lambda
Good morning everyone,
As I mentioned in my post yesterday, our research projects for the weekend are block,procs,lambdas and ruby gems. This post will be focused on blocks,procs and lambdas and I will write a separate one on ruby gems.
Block
A Ruby block is a contained  bit of code which can be executed and cannot be saved in a variable (kind of as a one-night stand). Block syntax uses either do...end or curly braces {}. Please keep in mind that we will need to use a block with an iterator like .each and .times. For example:
1. array = [ "hello", 'bonjour', 'hola', 'ciao']
array.each do |greeting|
  puts greeting
end
# ==> Prints hello, bonjour, hola, ciao on separate lines
A block is provided here to execute an instruction for each element in the collection (i.e. an array or hash). This can be rewritten, using the curly braces:
array.each { |greeting| puts greeting } # ==> Prints hello, bonjour, hola, ciao on separate lines
We can also use one or more variables in our block. Those variables are local to the block alone, so they will be destroyed once the block is executed. Thus, if we had two blocks, we could use the variable ‘greeting’ in both of them, and one wouldn’t affect the other.
So, why do some methods accept a block and others don’t? It’s because methods that accept blocks have a way of transferring control from the calling method to the block and back again. We can build this into the methods we define by using the yield keyword. Please have a look at the example below:
def yield_test
  puts "We're in the method!"
  yield
  puts "We're back in the method!"
end
yield_test { puts ">>> We're in the block!" }
==> We're in the method!
    >>> We're in the block!
    We're back in the method!
Procs
We have said earlier that blocks cannot be saved to a variable. The difference between a Proc and a block is that a Proc can be saved and executed again and again (kinda being in a relationship :)). You can define a Proc as follows, using do...end or {} and call it by using Ruby’s .call method.
greeting = Proc.new do
  puts "Hello!"
end
greeting.call ==> 'Hello'
greeting = Proc.new { puts "Hola!" }
greeting.call ==> "Hola!"
You can also pass arguments to Procs:
greeting = Proc.new { |name| puts "Hello #{name}!"}
greeting.call("Zhivko") ==> Hello Zhivko!
So why Procs? Why bother saving our blocks as procs? There are two main advantages:
- Procs are full-fledged objects, so they have all the powers and abilities of objects. (Blocks do not.)
 - Unlike blocks, procs can be called over and over without rewriting them. This prevents us from having to retype the contents of our block every time we need to execute a particular bit of code.
 
Lambdas
Lambdas are similar to Procs and they are also objects. Lambdas’s syntax is slightly different:
def test_lambda(lambda)
  puts "I am not a lambda!"
  lambda.call
end
test_lambda(lambda { puts "Magic, I am lambda!"} )
==> I am not a lambda
    Magic, I am lambda!
As you can see Procs and lambdas are quite similar. However, there are few things to keep in mind:
- 
    
A lambda cares how many arguments we pass to it (are you my valentine?), whereas a proc doesn’t. This means that we will get an error if we pass the wrong number of arguments to a lambda. In the meantime, a proc will just take what it needs and return nil for any that are missing.
 - 
    
When a lambda returns within a method, the method continues to execute (sharing is caring), whereas a proc immediately returns its value and exits the method.
 
Let’s look at the following examples:
def naughty_proc
  hello = Proc.new { return "Hi, Bye!"}
  hello.call
  puts "Wait, Holaaa!"
end
def lovely_lambda
  hello = lambda { return "Hi, Bye!" }
  hello.call
  puts "Wait, Holaaa!"
end
puts naughty_proc
puts lovely_lambda
=> Hi, Bye!
   Hi, Bye!
   Wait, Holaaa!
Zhivko