Boolean Enumerators
Objectives
Understand return values for enumerators.
Use true/false expressions within a block.
Use the
#all?
enumerator to create a true/false return value.Use the
#none?
enumerator to create a true/false return value.Use the
#any?
enumerator to create a true/false return value.Use the
#include?
enumerator to create a true/false return value.
Overview
When we are iterating over objects in a collection like with #each
we generally don't care about the return values.
If you run this code in IRB, you'll see:
You can see the block did what we intended it to do, it printed our output. You'll notice the last line also indicates that the #each
method also returned a value. All expressions in ruby must return a value. When you use #each
on a collection, the return value is always the original collection. Nothing you do inside the block you pass #each
will ever change the return value. But that's not always the case. With other enumerator methods, the return value of the method is very much dependent on the block.
#all?
#all?
Imagine wanting to know if all the numbers in an array are odd. You could use each with something like:
That works, the end value of all_odd
will be false because 2
flipped the all_odd
variable to false. However, something so simple - checking if all the elements in this array are odd - isn't being expressed clearly. Worse than our code not expressing our intention is that our code requires us to maintain variable state, all_odd
, which can easily lead to errors (say if some other piece of code accidentally changes that variable value).
Consider the following example using #all?
:
The rule for the #all?
enumerator is that the block passed to it must return true
for every iteration for the entire #all?
expression or method to return true
. If we introduce an even number to the collection, the return value will change.
That's the rule for #all?
- every iteration, every loop of the block must return true
. When the block encounters the value 2
for number
, it will run the expression 2.odd?
which will return false
. Because there was at least one iteration of the block that had a false
return value, the entire #all?
expression returns false
.
#none?
#none?
Imagine the opposite of #all?
, a method #none?
, where we are interested in none of the elements in a collection producing a true expression within the block passed to #none?
.
The entire expression #none?
returns true because none of those numbers will produce a true
expression when asked within the block if they are even. Compare the code above to the code required to test that condition using #each
:
These high-level boolean enumerators like #all?
and #none?
are way cleaner for evaluating elements in a collection for true
/false
conditions.
To recap, if any of the elements in the collection evaluate to true
when passed to the block, #none?
will return false
. If none of the elements evaluate to true
, #none?
will return true
.
#any?
#any?
Sometimes you want to be a bit more forgiving than #all?
or #none?
and just ensure that at least one element in a collection will create a true
expression within the block passed. #any?
is perfect for this. The #any?
enumerator will return true if at least one iteration of the block evaluates to true, but false if none of them do.
The #any?
expression above will return true
because at least one element, 100
, will produce a true
evaluation in the block.
#include?
#include?
Whereas #any?
is useful for evaluating the truthiness of the logic of a block, #include?
is helpful if you'd like to merely compare actual contents of a known value.
#include?
will return true
if the given element exists in the object. If it doesn't find a match, it will return false
.
The #include?
expression first returns true
because the_numbers[5] == 42
. When it is run with 6
, it will evaluate to false
since that item is not present in the array.
Last updated