Closures and Scope
Capturing variables.
Closures and Scope is a free Ruby Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Ruby Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Capturing Variables
A closure is a function that remembers the variables from the place where it was defined, even after that place has finished running. Procs and lambdas are closures.
name = "Ada"
greeter = -> { puts "Hello, #{name}" }
greeter.callThe Variable Travels With It
The closure does not copy the value; it keeps a live reference to the variable. Change the variable later and the closure sees the new value.
count = 0
reader = -> { count }
count = 5
puts reader.callClosures Can Mutate
Because the reference is live, a closure can also modify the captured variable.
total = 0
adder = ->(n) { total += n }
adder.call(3)
adder.call(7)
puts totalSurviving the Enclosing Method
The captured variable lives on as long as the closure does, even after the method that created it returns.
def counter
n = 0
-> { n += 1 }
end
c = counter
puts c.call
puts c.call
puts c.callIndependent States
Each call to the factory method makes a fresh variable, so separate closures keep separate state.
def counter
n = 0
-> { n += 1 }
end
a = counter
b = counter
puts a.call
puts a.call
puts b.callBlock Parameters Are Local
Parameters declared in the pipes are local to the block and never leak outside, even if a same-named variable exists.
x = 100
[1, 2, 3].each { |x| }
puts x # still 100Block-Local Variables
List extra names after a semicolon in the pipes to force them to be block-local, shielding outer variables from accidental change.
y = "outer"
[1].each { |i; y| y = "inner" }
puts y # unchangedBuilding Configurable Functions
Closures let you bake configuration into a function once and reuse it many times.
def power_of(exp)
->(base) { base ** exp }
end
square = power_of(2)
cube = power_of(3)
puts square.call(5)
puts cube.call(2)Closures in Iteration
A common gotcha: a closure created in a loop captures the variable, not a snapshot. Building closures per-iteration captures each value separately.
funcs = [1, 2, 3].map { |i| -> { i } }
puts funcs.map(&:call).inspectEncapsulating Private State
Closures can hide state behind functions, an early form of objects. Here the balance is unreachable except through the returned lambdas.
def make_account(start)
balance = start
deposit = ->(n) { balance += n }
show = -> { balance }
[deposit, show]
end
dep, show = make_account(100)
dep.call(50)
puts show.callPutting It Together
Closures bind code to its birthplace:
- They capture live references to surrounding variables.
- State survives after the enclosing method returns.
- Each closure keeps its own independent variables.
def tagger(prefix)
->(text) { "[#{prefix}] #{text}" }
end
warn = tagger("WARN")
puts warn.call("low disk space")Quick Check
Test your understanding of closures.
Recap
You learned closures and scope:
- Procs and lambdas capture surrounding variables by reference.
- Captured state outlives the enclosing method.
- Each closure holds independent state.
- Block parameters stay local; use
;for block-local vars.
def stepper(by)
pos = 0
-> { pos += by }
end
s = stepper(5)
puts s.call
puts s.callFrequently asked questions
Is the “Closures and Scope” lesson free?
Yes — the full text of “Closures and Scope” is free to read here on the web, and the Ruby Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Ruby Academy course, upgrade to CoddyKit PRO.
What will I learn in “Closures and Scope”?
Capturing variables. You practise Ruby Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Ruby Academy?
No prior experience is required. Ruby Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Closures and Scope” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Ruby Academy lesson?
Yes. Every Ruby Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Blocks Recap
- Procs
- Lambdas
- Closures and Scope