Bird
Raised Fist0
Rubyprogramming~30 mins

Closures and variable binding in Ruby - Mini Project: Build & Apply

Choose your learning style10 modes available
Closures and Variable Binding in Ruby
📖 Scenario: Imagine you are creating a simple greeting card generator. Each card has a personalized message that includes the recipient's name and a special number. You want to create a function that remembers the special number and uses it whenever you greet someone.
🎯 Goal: Build a Ruby program that demonstrates how closures capture variable bindings by creating a greeting function that remembers a special number and uses it to greet different people.
📋 What You'll Learn
Create a variable to hold a special number
Define a closure (lambda) that uses the special number and a name parameter
Change the special number after defining the closure
Call the closure with different names to see how variable binding works
💡 Why This Matters
🌍 Real World
Closures are used in Ruby for callbacks, event handlers, and to create functions that remember state without using global variables.
💼 Career
Understanding closures helps in writing clean, modular Ruby code and is important for roles involving Ruby on Rails or scripting.
Progress0 / 4 steps
1
Create a variable called special_number and set it to 7
Create a variable called special_number and set it to the integer 7.
Ruby
Hint

Use = to assign the value 7 to special_number.

2
Define a closure called greet that takes a name parameter and returns a greeting string using special_number
Define a closure called greet using lambda that takes one parameter name and returns the string "Hello, #{name}! Your special number is #{special_number}.".
Ruby
Hint

Use lambda { |name| ... } to create the closure and use string interpolation with #{}.

3
Change special_number to 42 after defining greet
Change the value of special_number to 42 after the greet lambda is defined.
Ruby
Hint

Simply assign 42 to special_number after the lambda definition.

4
Call greet with "Alice" and "Bob" and print the results
Call the greet lambda with the argument "Alice" and print the result. Then call greet with "Bob" and print the result.
Ruby
Hint

Use puts greet.call("Alice") and puts greet.call("Bob") to print the greetings.

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