2

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?

1 Answer 1

3

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

Sign up to request clarification or add additional context in comments.

5 Comments

This step through makes sense, the part thats difficult for me is how the (5) is making it's way to "proc3" in the original code. I know we "call" doubleThenSquare but doubleThenSquare itself isn't a proc function, it calls a method with a proc function in it (lets call that proc3). So thats where my confusion lies. Since we are actually calling something that is storing the return value of a method WITH a proc function in it...but not an actual proc function itself.
doubleThenSquare is a variable that is assigned the proc returned by compose(doubleIt, squareIt). That proc has a variable, but that variable is not assigned a value (e.g. 5) until doubleThenSquare is called.
Ah so it's able to pass it because a proc is being returned by compose...man that's confusing, since I assumed calling a proc it would need a variable directly (whatever you are calling)
Yes, you've got it. There's an analogous situation with methods. Suppose def m(x) 2*x end. We could then write method(:m).call(3) #=> 6 or public_send(:m, 3) #=> 6. method(:m) converts a method name (:m) to a method object. Being an object, it can be passed around like a proc, and like a proc, is invoked with call (but with Method#call, not Proc#call).
I guess it's not too crazy hopefully for that to be slighty confusing to me I hope haha (I just started learning ruby)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.