Bird
Raised Fist0
Rubyprogramming~5 mins

Closures and variable binding in Ruby

Choose your learning style10 modes available
Introduction
Closures let you keep a little piece of code and the variables it uses together, so you can use them later even outside their original place.
When you want to remember some settings or values inside a small piece of code to use later.
When you create a function inside another function and want the inner one to use variables from the outer one.
When you want to make a custom action that keeps some information hidden but still works when called.
When you want to delay running some code but keep the current values it needs.
Syntax
Ruby
def outer_function
  x = 10
  inner_function = -> { puts x }
  inner_function
end

closure = outer_function
closure.call
The inner function (closure) remembers the variable x from the outer function.
In Ruby, closures can be created with lambdas (->) or blocks.
Examples
This creates a closure that remembers the message 'Hello!' and prints it when called.
Ruby
def make_printer(msg)
  -> { puts msg }
end

printer = make_printer("Hello!")
printer.call
The closure remembers and updates the count variable each time it is called.
Ruby
def counter
  count = 0
  -> { count += 1 }
end

c = counter()
puts c.call
puts c.call
The closure uses the current value of x when called, showing variable binding at call time.
Ruby
x = 5
closure = -> { puts x }
x = 10
closure.call
Sample Program
This program creates a closure that remembers the greeting message for 'Alice' and prints it when called.
Ruby
def greeting_maker(name)
  greeting = "Hello, #{name}!"
  -> { puts greeting }
end

say_hello = greeting_maker("Alice")
say_hello.call
OutputSuccess
Important Notes
Closures keep variables alive even after the outer function finishes.
Changing a variable outside after creating a closure may or may not affect the closure depending on when the variable is accessed.
Closures are useful for creating functions with memory or delayed actions.
Summary
Closures are functions that remember variables from where they were made.
They let you keep data hidden but usable later.
In Ruby, closures are often made with lambdas or blocks.

Practice

(1/5)
1. What is a closure in Ruby?
easy
A. A variable that changes its value automatically
B. A method that can only be called once
C. A function that remembers variables from its creation context
D. A class that cannot be inherited

Solution

  1. 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.
  2. 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.
  3. Final Answer:

    A function that remembers variables from its creation context -> Option C
  4. Quick Check:

    Closure = function remembering variables [OK]
Hint: Closures remember variables where they were made [OK]
Common Mistakes:
  • Thinking closures are just methods
  • Confusing closures with classes
  • Believing closures change variable values automatically
2. Which of the following is the correct way to create a closure using a lambda in Ruby?
easy
A. closure = lambda { |x| x * 2 }
B. closure = def(x) x * 2 end
C. closure = function(x) { x * 2 }
D. closure = -> x x * 2

Solution

  1. Step 1: Identify Ruby lambda syntax

    In Ruby, lambdas can be created with lambda { |args| ... } or ->(args) { ... }.
  2. Step 2: Check each option

    closure = lambda { |x| x * 2 } uses lambda { |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.
  3. Final Answer:

    closure = lambda { |x| x * 2 } -> Option A
  4. Quick Check:

    Correct lambda syntax = closure = lambda { |x| x * 2 } [OK]
Hint: Use lambda { |args| ... } for Ruby closures [OK]
Common Mistakes:
  • Using JavaScript or Python syntax
  • Omitting parentheses in arrow lambdas
  • Trying to define lambdas with def keyword
3. What will be the output of this Ruby code?
def make_closures
  closures = []
  3.times do |i|
    closures << lambda { i }
  end
  closures
end

closures = make_closures
closures.each { |c| puts c.call }
medium
A. 2 2 2
B. 0 1 2
C. 0 0 0
D. Error: undefined variable i

Solution

  1. Step 1: Understand variable binding in block

    Ruby lambdas capture block variables like i by value in this context, so each lambda remembers its own i value.
  2. Step 2: Evaluate each lambda call

    The loop sets i to 0, 1, 2 sequentially. Each lambda captures the current i value, so outputs are 0, 1, 2 respectively.
  3. Final Answer:

    0 1 2 -> Option B
  4. Quick Check:

    Lambdas capture distinct values per iteration [OK]
Hint: Ruby block vars in closures captured by value per iteration [OK]
Common Mistakes:
  • Thinking lambdas capture shared variable (all 2)
  • Thinking last value is 3 (off-by-one)
  • Expecting error or all zeros
4. Find the error in this Ruby code that tries to create closures:
closures = []
3.times do |i|
  closures << lambda { j }
  j = i
end
closures.each { |c| puts c.call }
medium
A. Variable j is used before assignment inside the lambda
B. Lambda syntax is incorrect
C. times method cannot be used with blocks
D. closures array is not initialized

Solution

  1. Step 1: Identify variable usage inside lambda

    The lambda uses variable j before it is assigned any value in the block, causing an error when called.
  2. Step 2: Understand variable binding timing

    Since j is assigned after lambda creation, the lambda captures j as nil or undefined at call time, causing an error.
  3. Final Answer:

    Variable j is used before assignment inside the lambda -> Option A
  4. Quick Check:

    Use variables after assignment in closures [OK]
Hint: Assign variables before using them in closures [OK]
Common Mistakes:
  • Assuming lambda syntax is wrong
  • Thinking times method is invalid
  • Ignoring variable initialization order
5. How can you modify this Ruby code to create closures that each remember a different value of i even if i changes later?
closures = []
3.times do |i|
  closures << lambda { i }
end
closures.each { |c| puts c.call }
hard
A. Call closures inside the times block
B. Change lambda to proc
C. Use global variable $i instead of i
D. Use a local variable inside the block to capture i: val = i; closures << lambda { val }

Solution

  1. Step 1: Understand variable capture in closures

    Closures capture variables by reference, so if i changes later, all lambdas see the last value.
  2. Step 2: Use a local variable to capture current value

    Assign val = i inside the block, then create lambda using val. This captures the value at that iteration.
  3. Final Answer:

    Use a local variable inside the block to capture i: val = i; closures << lambda { val } -> Option D
  4. Quick Check:

    Capture current value with local variable [OK]
Hint: Assign loop variable to local var inside block for closure [OK]
Common Mistakes:
  • Thinking proc changes variable capture behavior
  • Using global variables which share state
  • Calling closures too early inside loop
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard