Pop quiz, hotshot: What does the following Ruby expression return?
1
| |
It turns out I’m not much of a hotshot, because this how I reasoned through this question while at work today:
Array#mapevaluates the block for each member of the array and returns a new array of the returned values, in order.- When
n == 1orn == 3, the block evaluates to2*n. - However, when
n == 2we hit thenextkeyword and nothing gets evaluated. - Therefore this expression returns
[2,6].
Reinforcing this line of reasoning, a very similar expression,
1
| |
gives the analog of this result:
it prints “2” and then “6” and then return.
The iteration that hits next just gets skipped.
Analogously, the version with map should return [2,6]
Wrong!
In fact, the answer to the quiz is…
1
| |
The error in the reasoning above is contained in premise (3).
It turns out that when next is evaluated, it returns nil.
Similarly,
1
| |
returns the same array, [2, nil, 6], because ... if false returns nil no matter what (syntactically valid) expression ... is.
So, if you’re using map, and you want to skip some elements, you can’t just use next or if.
You also need to deal with the nils when you’re done, like this:
1
| |
Alternatively—although it’s probably more expensive—you could select the elements you want before proceeding with the operations you want to perform on them:
1
| |
Let me know in the comments if you can think of a generalizable implementation that’s more elegant than either of these. In the meantime, may you never make the same mistake I made!