Reputation: 193
I have this code
arr = [1, 2, 3].select do |n|
n + 2
puts n
end
The output is
1
2
3
and the return value is
[]
Then I have this code
arr = [1, 2, 3].select do |n|
n + 2
end
and the return value is
[1, 2, 3]
So I know that Array#select invokes the block passing in successive elements from self, returning an array containing those elements for which the block returns a true value. How does it behave in those code examples so I could understand why it returns these values.
Upvotes: 0
Views: 5042
Reputation: 33
Array#select
returns a new array with all the elements that returned true
from the block. It does this by iterating over each element, passing it to the block, running the block if the block returns true it puts the element in the new array if not it will skip it and once done it will return a new array.
With that said there are a few other things we should know first before delving into the problem you're having.
1) In Ruby there's a concept called Truthiness. That means that every element except for nil
and false
evaluates to true
. Take for example if I ran this conditional
if 'happy puppy'
puts "I'm the happiest puppy"
end
You'd see that I'm the happiest puppy
is output. That's because the string, not being false
or nil
, will evaluate to true
. Conversely if ran this code
if nil
puts "Truthiness means all things evaluate to true except nil and false"
end
In this example, the conditional wouldn't output the string because nil
doesn't evaluate to true.
2) Pay careful attention to what a method outputs and returns. In the case of Kernel#Puts it outputs n
and returns nil
. When the block being passed to Array#select
is invoked it runs each line of code in the block including puts
. That's why we see each number output. Then, this is the important part, it returns nil
. Now remember the rules of Truthiness? Because this is the last line of code in the block it's the implicit return of the entire block. That means the block will return nil
which evaluates to false.
3) Now on to Array#select
, it works by iterating over each element in an array and invoking the block on it. Based on the return value of the block it'll decide whether or not the element belongs in the return array. In your first example, puts
is used on the last line and returns nil
which means that the block will always evaluate to false. That's why it outputs the element but then returns an empty array. In the second example, the last line in the block is n+2
which will evaluate to an integer. This is where truthiness comes in to play, an integer (or anything besides false or nil) will always evaluate to true. This means the block always returns true. That's why all the elements are returned in the array.
Upvotes: 1
Reputation: 4801
Array#select
creates a new array using the elements of your array that return truthy from the block.
In your first case, the last line of your block is a puts
statement which always returns nil. Hence the []
.
In your second case, the last line of your block is always a number, so always truthy. Hence the output equals the input.
Upvotes: 5