Blocks are chunks of code passed to methods. They are one of Ruby's most powerful features — you'll see them everywhere in Rails and standard libraries.
Blocks with yield
Ruby
def timer
start = Time.now
yield # runs the block passed by the caller
elapsed = Time.now - start
puts "Done in #{elapsed.round(2)}s"
end
timer { sleep(1) } # "Done in 1.0s"Block Arguments
Ruby
def each_with_label(items)
items.each_with_index do |item, i|
yield i, item
end
end
each_with_label(["apple", "banana", "cherry"]) do |index, fruit|
puts "#{index + 1}. #{fruit}"
end
# 1. apple
# 2. banana
# 3. cherrydo/end vs {}
Convention: use do...end for multi-line blocks and { } for single-line:
Ruby
# Single line
[1, 2, 3].map { |n| n * 2 }
# Multi-line
[1, 2, 3].map do |n|
doubled = n * 2
puts doubled
doubled
endProcs
A Proc is an object that wraps a block:
Ruby
square = Proc.new { |n| n * n }
square.call(5) # 25
square.call(10) # 100
# Shorthand
triple = ->(n) { n * 3 }
triple.call(4) # 12Lambdas vs Procs
Ruby
greet = lambda { |name| "Hello, #{name}!" }
greet = ->(name) { "Hello, #{name}!" } # same thing
# Key difference: arity checking
my_proc = Proc.new { |a, b| [a, b] }
my_proc.call(1) # [1, nil] — no error, extra args ignored
my_lambda = ->(a, b) { [a, b] }
my_lambda.call(1) # ArgumentError — wrong number of argumentsClosures
Procs and lambdas capture their surrounding scope:
Ruby
def make_counter
count = 0
incrementer = -> { count += 1 }
resetter = -> { count = 0 }
[incrementer, resetter]
end
inc, reset = make_counter
inc.call # 1
inc.call # 2
reset.call # 0
inc.call # 1Useful Higher-Order Methods
Ruby
nums = [1, 2, 3, 4, 5]
nums.map { |n| n * 2 } # [2, 4, 6, 8, 10]
nums.select { |n| n.even? } # [2, 4]
nums.reject { |n| n.even? } # [1, 3, 5]
nums.find { |n| n > 3 } # 4
nums.any? { |n| n > 4 } # true
nums.all? { |n| n > 0 } # true
nums.none? { |n| n < 0 } # true
nums.reduce(0) { |sum, n| sum + n } # 15Tips
- Blocks are not objects — Procs and lambdas are.
- Use
yieldto call a block from within a method. - Prefer
lambdaoverProc.newfor strict argument checking.
Next: testing.