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