Pop quiz, hotshot: What does the following Ruby expression return?
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.
n == 1or
n == 3, the block evaluates to
- However, when
n == 2we hit the
nextkeyword and nothing gets evaluated.
- Therefore this expression returns
Reinforcing this line of reasoning, a very similar expression,
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
In fact, the answer to the quiz is…
The error in the reasoning above is contained in premise (3).
It turns out that when
next is evaluated, it returns
returns the same array,
[2, nil, 6], because
... if false returns nil no matter what (syntactically valid) expression
So, if you’re using
map, and you want to skip some elements, you can’t just use
You also need to deal with the
nils when you’re done, like this:
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:
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!