Ruby Academy · Lesson

Closures and Scope

Capturing variables.

Lesson 4 of 413 steps

Closures and Scope is a free Ruby Academy lesson on CoddyKit. This is lesson 4 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Ruby Academy learning path, and your progress syncs across the web and the CoddyKit app. The Ruby Academy course includes 4 lessons in total.

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.call

The 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.call

Closures 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 total

Surviving 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.call

Independent 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.call

Block 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 100

Block-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  # unchanged

Building 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).inspect

Encapsulating 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.call

Putting 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.call
Free to start

Learn Ruby with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
29
Lessons
109

Frequently Asked Questions

Is the “Closures and Scope” lesson free?

Yes — any 3 lessons of the Ruby Academy learning path, including “Closures and Scope”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Ruby Academy course includes 4 lessons in total.

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, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.

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

  1. Blocks Recap
  2. Procs
  3. Lambdas
  4. Closures and Scope
← Back to Ruby Academy