Blocks and Yield

Block

A code block passed to a method that can be called later

Yield

The action of calling that block

This means the method stops to run the block.

class Dog

  attr_accessor :location
    
  def initialize
    @location = :home
  end

  def trick
    puts "I'm gonna do a trick at #{location}!"
    trick_result = yield location
    puts "My trick was #{trick_result}!"
  end

end
fido = Dog.new
tesla = Dog.new
my_pets = [fido, tesla]
my_pets.each{|pet| pet.location = :park} #going to the dog park

fido.trick do |loc|
  if loc == :home
    "sit"
  else
    "speak"
  end
end
# => My trick was speak!

tesla.trick do |loc|
  if loc == :home
    "roll over"
  else
    "heel"
  end
end
# => My trick was heel!

Why

  • custom actions rather actions rather than making new methods
  • yield control to outside the method

What if you could store the block as a variable?

Lambdas

Why to use

Allow you to store blocks as variables

You can also pass multiple procs/lambdas to a method, while only one block can be passed in a method call.

l1 = lambda{|x| puts "#{x}!"}
l2 = lambda{|x| puts "#{x}."}

l1.call("hi")
l2.call("hi")

def call_some_stuff(first, second)
  first.call("hello")
  second.call("hello")
end

call_some_stuff(l1, l2)
# => 
hello!
hello.

Using as blocks

l = lambda{|x| print x}
[1,2,3,4].each(&l) # => 1234

Lambdas

`return` returns from the lambda itself

 

Procs

`return` returns from the calling method

Will not give an error if given the wrong number of arguments

Yield

By Isaac

Yield

  • 431