Blocks & Yield
A block is an anonymous chunk of code passed to a method. Blocks power Ruby’s expressive iteration: each, map, tap, open(…) { |f| … }. Procs and lambdas are blocks promoted to objects.
Blocks, yield, procs, lambdas
EXAMPLE
# 1) Blocks: do…end OR { … }
[1, 2, 3].each do |n|
puts n * 2
end
[1, 2, 3].map { |n| n * 2 }
# 2) Yield to a block from your own method
def with_timer
start = Time.now
result = yield
puts "took \#{Time.now - start}s"
result
end
rows = with_timer { Database.query('SELECT * FROM users') }
# 3) Pass arguments to the block
def each_pair(hash)
hash.each { |k, v| yield k, v }
end
# 4) Optional block — block_given?
def debug(msg)
if block_given?
yield msg # let caller customise the format
else
puts msg
end
end
debug('hi')
debug('hi') { |m| warn "[debug] \#{m.upcase}" }
# 5) Explicit block parameter — capture as a Proc
def retry_with(times, &block)
times.times do |i|
begin
return block.call(i)
rescue StandardError
sleep(2**i)
end
end
end
retry_with(3) { |i| fetch_remote }
# 6) Proc vs Lambda — strictness about arguments
adder = ->(a, b) { a + b } # lambda — strict (wrong arity raises)
adder.call(1, 2)
adder.(1, 2) # short form
adder[1, 2] # square-bracket form
loose = proc { |a, b| a.to_i + b.to_i } # proc — lax, missing args nil
loose.call(1)
# 7) Convert blocks ⇄ symbols
[1, 2, 3, 4].map(&:to_s) # &:to_s == { |x| x.to_s }
logger = ->(line) { warn line }
run_pipeline(&logger) # pass a lambda as a block
# 8) yield_self / then — pipeline a value
result = read_file(path)
.then { |raw| parse_csv(raw) }
.then { |rows| reject_blanks(rows) }
.then { |rows| index_by(&:id) }
# 9) tap — peek at a value without breaking the chain
[1, 2, 3]
.tap { |a| puts "before: \#{a}" }
.map { |n| n * 2 }
.tap { |a| puts "after: \#{a}" }
Why it matters
&:method_name is the most common Ruby shorthand. users.map(&:name) reads like English, runs as fast as a hand-written block, and keeps intent obvious.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Exercise
Run the caller's block.
def repeat(n)
n.times {
}
end
Five letters.
Discussion
Loading…