# A Lesson in Passing Blocks in Ruby
# http://mudge.name/2011/01/26/passing-blocks-in-ruby-without-block.html
# FYI
# Do remember to actually check that a block was passed to the method with block_given?
# There are several main ways to receive blocks in a method in Ruby: the first is to use the yield keyword like so:
# Method 1 -- using yield
# It is clearly preferable to choose yield over &block
def speak
puts yield
end
speak { "Hello" }
# => Hello
# Method 2 -- method signature with an ampersand method(&block) which will then create a Proc object
# The problem with the second approach is that instantiating a new Proc object incurs a surprisingly heavy performance penalty
def speak(&block)
puts block.call
end
speak { "Hello" }
# => Hello
# Method 3 -- call Proc.new, this isn't removes the expense of Proc calling found in Method 2
def speak
puts Proc.new.call
end
speak { "Hello" }
# => Hello
# What if you need to pass a block to another method?
# Example: here is a class that implements a method tell_ape which delegates to another, more generic method named tell
# Method 1
# My preference, cleaner. Downside: you can't look at the method signature to see if it takes a block
# you actually have to read more into the code
# Upside: this has heigher performance than using &block
class Monkey
def self.tell_ape
tell("ape") {yield}
end
def self.tell(name)
puts "#{name}: #{yield}"
end
end
Monkey.tell_ape { "ook!" }
# => ape: ook!
class Monkey
def self.tell_ape
tell("ape", &Proc.new)
end
def self.tell(name)
puts "#{name}: #{yield}"
end
end
Monkey.tell_ape { "ook!" }
# => ape: ook!
class Monkey
def self.tell_ape(&block)
tell("ape", &block)
end
def self.tell(name, &block)
puts "#{name}: #{block.call}"
end
end
Monkey.tell_ape { "ook!" }
# => ape: ook!