Bird
Raised Fist0
Rubyprogramming~10 mins

Proc composition in Ruby - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Proc composition
Define Proc A
↓
Define Proc B
↓
Compose Proc C = B after A
↓
Call Proc C with input
↓
Proc A processes input
↓
Proc B processes Proc A output
↓
Return final result
We define two Procs, then create a new Proc by composing them. Calling the composed Proc runs the first, then passes its output to the second.
Execution Sample
Ruby
a = Proc.new { |x| x + 2 }
b = Proc.new { |y| y * 3 }
c = Proc.new { |z| b.call(a.call(z)) }
result = c.call(4)
puts result
This code composes two Procs: adds 2, then multiplies by 3, and calls the composition with 4.
Execution Table
StepActionInputProc CalledOutputNotes
1Call c.call(4)4c?Start composition call
2Inside c: call a.call(4)4a6a adds 2 to 4
3Inside c: call b.call(6)6b18b multiplies 6 by 3
4Return from c.call(4)4c18Final result is 18
💡 Finished composition: output 18 returned after running a then b
Variable Tracker
VariableStartAfter Step 2After Step 3Final
inputundefined444
a.call resultundefined666
b.call resultundefinedundefined1818
c.call resultundefinedundefinedundefined18
Key Moments - 3 Insights
Why do we call a.call(z) inside the Proc c instead of just using a(z)?
In Ruby, Procs are objects and need .call to execute. The execution_table row 2 shows a.call(4) producing 6.
What happens if we switch the order and call a.call(b.call(z)) instead?
The order changes the result because b runs first. The execution_table shows the current order: a then b, which matters for output.
Why does c.call(4) return 18?
Because a adds 2 to 4 (6), then b multiplies 6 by 3 (18), as shown in execution_table rows 2 and 3.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the output of a.call(4) at step 2?
A8
B6
C12
D18
💡 Hint
Check execution_table row 2 under Output column
At which step does the Proc b get called during c.call(4)?
AStep 1
BStep 2
CStep 3
DStep 4
💡 Hint
Look at execution_table rows and find where b.call is executed
If we change Proc b to multiply by 4 instead of 3, what would c.call(4) output be?
A24
B18
C20
D16
💡 Hint
Use variable_tracker to find a.call(4) = 6, then multiply by 4
Concept Snapshot
Proc composition in Ruby:
- Define Procs: a = Proc.new { |x| ... }
- Compose: c = Proc.new { |z| b.call(a.call(z)) }
- Call composed Proc: c.call(input)
- Output is b applied to a's output
- Use .call to execute Procs
- Order matters: a then b here
Full Transcript
This example shows how to compose two Procs in Ruby. We define Proc a that adds 2 to input, and Proc b that multiplies input by 3. Then we create Proc c that calls a, then passes its result to b. Calling c.call(4) runs a.call(4) which gives 6, then b.call(6) which gives 18. The final output is 18. We track each step in the execution table and variable changes. Key points include using .call to run Procs and understanding the order of composition affects the result.

Practice

(1/5)
1. What does the >> operator do when used with two Procs in Ruby?
easy
A. It merges two Procs into one that runs them both in parallel.
B. It creates a new Proc that runs the first Proc, then passes its result to the second Proc.
C. It swaps the order of execution of two Procs.
D. It deletes the second Proc and keeps only the first.

Solution

  1. Step 1: Understand Proc composition operator

    The >> operator chains two Procs so the output of the first becomes input of the second.
  2. Step 2: Explain the effect of chaining

    Calling the combined Proc runs the first, then passes its result to the second, producing a final result.
  3. Final Answer:

    It creates a new Proc that runs the first Proc, then passes its result to the second Proc. -> Option B
  4. Quick Check:

    Proc composition = chaining with >> [OK]
Hint: Remember >> chains Procs passing output as input [OK]
Common Mistakes:
  • Thinking >> runs Procs in parallel
  • Assuming >> swaps execution order
  • Believing >> deletes one Proc
2. Which of the following is the correct syntax to compose two Procs p1 and p2 in Ruby?
easy
A. combined = p1 >> p2
B. combined = p1 >>> p2
C. combined = p1 << p2
D. combined = p1 >> p2.call

Solution

  1. Step 1: Recall correct Proc composition operator

    The operator to compose Procs is >>, which is written as >> but in Ruby code it is >> (two greater-than signs).
  2. Step 2: Check each option

    combined = p1 >> p2 uses >> correctly. combined = p1 >>> p2 uses three > which is invalid. combined = p1 << p2 uses << which is not for composition. combined = p1 >> p2.call calls p2 immediately, which is wrong.
  3. Final Answer:

    combined = p1 >> p2 -> Option A
  4. Quick Check:

    Proc composition syntax = p1 >> p2 [OK]
Hint: Use exactly two > signs to compose Procs [OK]
Common Mistakes:
  • Using >>> instead of >>
  • Using << instead of >>
  • Calling Proc instead of composing
3. What is the output of this Ruby code?
p1 = Proc.new { |x| x + 2 }
p2 = Proc.new { |y| y * 3 }
combined = p1 >> p2
puts combined.call(4)
medium
A. 18
B. 14
C. 20
D. 12

Solution

  1. Step 1: Evaluate first Proc with input 4

    p1 adds 2 to input: 4 + 2 = 6.
  2. Step 2: Pass result 6 to second Proc

    p2 multiplies input by 3: 6 * 3 = 18.
  3. Final Answer:

    18 -> Option A
  4. Quick Check:

    (4 + 2) * 3 = 18 [OK]
Hint: Apply first Proc, then second on result [OK]
Common Mistakes:
  • Adding instead of multiplying in second Proc
  • Multiplying first, then adding
  • Confusing order of Procs
4. Identify the error in this Ruby code that tries to compose two Procs:
p1 = Proc.new { |x| x * 2 }
p2 = Proc.new { |y| y + 5 }
combined = p1 >> p2.call
puts combined.call(3)
medium
A. Syntax error due to missing parentheses
B. Using wrong operator for composition
C. Missing block parameters in p1
D. Calling p2 immediately instead of composing

Solution

  1. Step 1: Check how p2 is used in composition

    The code uses p2.call which calls p2 immediately, returning a value, not a Proc.
  2. Step 2: Understand correct composition usage

    To compose, use p1 >> p2 without calling p2. Calling p2 breaks composition.
  3. Final Answer:

    Calling p2 immediately instead of composing -> Option D
  4. Quick Check:

    Compose Procs without calling them [OK]
Hint: Do not call Procs when composing, just use >> [OK]
Common Mistakes:
  • Calling Proc instead of composing
  • Using wrong operator like <<
  • Forgetting block parameters
5. Given these Procs:
p1 = Proc.new { |x| x.to_s }
p2 = Proc.new { |s| s + "!" }
p3 = Proc.new { |str| str.reverse }

How do you compose them so that calling the combined Proc with 5 returns "5!"?
hard
A. combined = p3 >> p2 >> p1
B. combined = p1 >> p2 >> p3
C. combined = p1 >> p3 >> p2
D. combined = p2 >> p1 >> p3

Solution

  1. Step 1: Understand each Proc's effect

    p1 converts number to string, p2 adds "!", p3 reverses string.
  2. Step 2: Find composition order to get "5!"

    "5".reverse = "5", so p1 >> p3 >> p2 gives: "5" -> "5" -> "5!". But p1 >> p2 >> p3: "5" -> "5!" -> "!5". Only A produces "5!".
  3. Final Answer:

    combined = p1 >> p3 >> p2 -> Option C
  4. Quick Check:

    to_s, reverse, then add ! = "5!" [OK]
Hint: Order Procs by desired transformations stepwise [OK]
Common Mistakes:
  • Putting p2 before p3 changes output to "!5"
  • Reversing order causes errors on non-string
  • Ignoring effect of reverse on "5!"
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