Search code examples
rubyproc

Passing procs and methods


I came across this code:

squareIt = Proc.new do |x|
  x * x
end

doubleIt = Proc.new do |x|
  x + x
end

def compose proc1, proc2
  Proc.new do |x|
    proc2.call(proc1.call(x))
  end
end

doubleThenSquare = compose(doubleIt, squareIt)
squareThenDouble = compose(squareIt, doubleIt)

doubleThenSquare.call(5)
squareThenDouble.call(5)

doubleThenSquare is called with 5. doubleThenSquare is equal to the return value of compose, which has its two parameters doubleIt and squareIt passed.

I don't see how 5 is passed all its way into the different procs Proc.new do |x|. How does it know what x is in each case?


Solution

  • Let's step through it.

    doubleIt = Proc.new do |x|
      x + x
    end
      #=> #<Proc:0x00000002326e08@(irb):1429>
    
    squareIt = Proc.new do |x|
      x * x
    end
      #=> #<Proc:0x00000002928bf8@(irb):1433>
    
    proc1 = doubleIt
    proc2 = squareIt
    

    compose returns the proc proc3.

    proc3 = Proc.new do |x|
        proc2.call(proc1.call(x))
    end
      #=> #<Proc:0x000000028e7608@(irb):1445>
    

    proc3.call(x) is executed in the same way as

    proc3_method(x)
    

    where

    def proc3_method(x)
      y = proc1.call(x)
      proc2.call(y)
    end
    

    When x = 5,

    y = proc1.call(5)
      #=> 10
    proc2.call(10)
      #=> 100
    

    proc3_method(5) therefore returns 100, as does proc3.call(5).