What if your code could remember things for you, like a helpful friend?
Why Closures and variable binding in Ruby? - Purpose & Use Cases
Imagine you want to create several small tasks that remember different numbers and add them later. You try to write each task by hand, copying and changing the number everywhere.
This manual way is slow and easy to mess up. If you forget to change one number, all tasks might add the same wrong number. It's hard to keep track and fix mistakes.
Closures let you write one task that remembers its own number automatically. Each task keeps its own memory, so you don't have to copy or change code by hand. This makes your code cleaner and safer.
def make_adder(n) return lambda { |x| x + n } end add_two = make_adder(2) add_three = make_adder(3) puts add_two.call(5) # 7 puts add_three.call(5) # 8
adders = [] [2, 3].each do |n| adders << lambda { |x| x + n } end puts adders[0].call(5) # 7 puts adders[1].call(5) # 8
Closures let you create flexible, reusable pieces of code that remember their own data without extra work.
Think of a coffee shop where each barista remembers your favorite drink. Closures are like that memory, so each barista (function) serves your special order without asking every time.
Manual copying of code for each value is slow and error-prone.
Closures capture and remember variables automatically.
This makes code easier to write, read, and maintain.
Practice
Solution
Step 1: Understand the definition of closure
A closure is a function or block that keeps access to variables from where it was created, even if called later.Step 2: Match the definition to options
A function that remembers variables from its creation context correctly describes this behavior. Other options describe unrelated concepts.Final Answer:
A function that remembers variables from its creation context -> Option CQuick Check:
Closure = function remembering variables [OK]
- Thinking closures are just methods
- Confusing closures with classes
- Believing closures change variable values automatically
Solution
Step 1: Identify Ruby lambda syntax
In Ruby, lambdas can be created withlambda { |args| ... }or->(args) { ... }.Step 2: Check each option
closure = lambda { |x| x * 2 } useslambda { |x| x * 2 }, which is valid. closure = def(x) x * 2 end uses invalid syntax for a lambda. closure = function(x) { x * 2 } uses JavaScript-like syntax. closure = -> x x * 2 misses parentheses in the arrow syntax, which is invalid.Final Answer:
closure = lambda { |x| x * 2 } -> Option AQuick Check:
Correct lambda syntax = closure = lambda { |x| x * 2 } [OK]
- Using JavaScript or Python syntax
- Omitting parentheses in arrow lambdas
- Trying to define lambdas with def keyword
def make_closures
closures = []
3.times do |i|
closures << lambda { i }
end
closures
end
closures = make_closures
closures.each { |c| puts c.call }Solution
Step 1: Understand variable binding in block
Ruby lambdas capture block variables likeiby value in this context, so each lambda remembers its ownivalue.Step 2: Evaluate each lambda call
The loop setsito 0, 1, 2 sequentially. Each lambda captures the currentivalue, so outputs are 0, 1, 2 respectively.Final Answer:
0 1 2 -> Option BQuick Check:
Lambdas capture distinct values per iteration [OK]
- Thinking lambdas capture shared variable (all 2)
- Thinking last value is 3 (off-by-one)
- Expecting error or all zeros
closures = []
3.times do |i|
closures << lambda { j }
j = i
end
closures.each { |c| puts c.call }Solution
Step 1: Identify variable usage inside lambda
The lambda uses variablejbefore it is assigned any value in the block, causing an error when called.Step 2: Understand variable binding timing
Sincejis assigned after lambda creation, the lambda capturesjas nil or undefined at call time, causing an error.Final Answer:
Variable j is used before assignment inside the lambda -> Option AQuick Check:
Use variables after assignment in closures [OK]
- Assuming lambda syntax is wrong
- Thinking times method is invalid
- Ignoring variable initialization order
i even if i changes later?
closures = []
3.times do |i|
closures << lambda { i }
end
closures.each { |c| puts c.call }Solution
Step 1: Understand variable capture in closures
Closures capture variables by reference, so ifichanges later, all lambdas see the last value.Step 2: Use a local variable to capture current value
Assignval = iinside the block, then create lambda usingval. This captures the value at that iteration.Final Answer:
Use a local variable inside the block to capture i:val = i; closures << lambda { val }-> Option DQuick Check:
Capture current value with local variable [OK]
- Thinking proc changes variable capture behavior
- Using global variables which share state
- Calling closures too early inside loop
Ready to prove it?
Pass the test and this pattern moves unknown
