7. Proc Syntax - Am I thinking about this correctly?



I'd like to step through the proc process. Please correct me where I may be incorrect.

floats = [1.2, 3.45, 0.91, 7.727, 11.42, 482.911]
round_down = Proc.new { |x| x = x.floor }
ints = floats.collect(&round_down)

1. The variable floats is given a number from the array. 1.2, 3.45, 0.91, etc.
2. The variable round_down is given a procedure. This line is skipped until it's called.
3. The variable ints is given floats.collect which, I think, gives it the value of each number in the array. At this point, in my mind, I think it looks like this: ints = 1.2(&round_down)
4. Now the round_down procedure is called. x is obviously 1.2 because putting the .floor method on it rounds it down to 1. But I don't know how x gets 1.2. If someone could explain that it would be great.


1) no, a reference to the whole array is assigned to it
2) a proc is created and a reference to it is assigned to round_down. The line is not skipped, otherwise you could remove without being able to see any difference in the code's behaviour. There's nothing to skip either. Nothing is invoking it, but there isn't anything saying it should be invoked so there is no "skipping"
3) no, a reference to the result of invoking floats.collect is assigned to ints. floats is an array so collect is an array method, that's what you're saying, "call your method named collect". You could write it this way as well: [1.2, 3.45, 0.91, 7.727, 11.42, 482.911].collect(&round_down) since that's what floats refers to.
4) your proc is repeatedly invoked by collect, each time it gives it an argument.


Think of .collect as being like .each. It has an internal pointer and iterates over the array it is called on. The parameter is the proc. The method calls the proc on each member of the array..


Thanks for your help. I understand 1 and 2 but I'm struggling with 3. I'm having a hard time putting it into normal English.

ints = floats.collect(&round_down)

Go to the floats array and collect each value in the array. Then perform the procedure in round_down. What I'm confused about is when .collect is called on floats, where does it store that value? And how does that value get assigned to x in the procedure?


ints = floats.collect(&round_down)

Is .collect on floats saying "get each value from the array?"


Yes. It is a method of the Array class, and therefore an attribute of the floats object. The difference between .collect() and .each() is that the latter does not return an array. .collect() does.

It can take a block, rather than a Proc, as in,

ints = floats.collect() { |x| x.floor }

In your code, the Proc could have been written like the block above.


The word "saying" suggests that there is meaning.
The only meaning in that line,

ints = floats.collect(&round_down)

is to convert round_down into a block and then call the method collect on the value that floats refers to, passing it the block. Once the method call has finished, assign the result to ints

That's what that line says. It says absolutely nothing about arrays or the values in them. That method has a certain behaviour, but your line is not detailing that behaviour, it just says to call a method.

If you have an array and you want to apply an operation on each value in it, then you can leverage that array's collect method (AKA map) to achieve that result. What you need to tell Ruby to make that happen is to invoke that method. That is what that line "says". Other lines elsewhere will be saying things about arrays and floating point numbers, and your line depends on that. But your line doesn't say those things.

X is an apple.
X is purple.

The second line is not saying that There is an apple and it's purple. It only says that X is purple. It also doesn't say what purple is, just that whatever purple refers to, that applies to X.
Together, those lines say that There is a purple apple.


Thanks for that explanation.

Let's see if I understand. ints is assigned the array floats. That array has an array method (.collect) called on it and it also accepts parameters (I hope that's the correct word.) The parameter is the procedure converted into a block using the &.

Perhaps it's the method I'm struggling to understand. Is it correct to say .collects assigns each value in the array to the variable defined in the block? By "variable defined in the block" I mean the one between the | | marks. Like so:
{ |x| x = x.floor }


As mentioned earlier, we do not need to assign anything to x. The value, x.floor is the return value.


is referred to as the block parameter. It is the variable that receives a value from .collect() as it iterates the array.


Awesome! This fills in the gap for me. The block parameter gets the value from the method on the array. Thanks for the help! You and

are saints for putting up with all these awful questions. Thanks again guys.


This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.