> For the complete documentation index, see [llms.txt](https://certil-remy.gitbook.io/learn/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://certil-remy.gitbook.io/learn/intro-to-tic-tac-toe/untitled-35.md).

# Boolean Enumerators

## Objectives

1. Understand return values for enumerators.
2. Use true/false expressions within a block.
3. Use the `#all?` enumerator to create a true/false return value.
4. Use the `#none?` enumerator to create a true/false return value.
5. Use the `#any?` enumerator to create a true/false return value.
6. 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.

```
["Red", "Yellow", "Blue"].each do |color|
  puts "There are #{color.length} letters in #{color}"
end #=> ["Red", "Yellow", "Blue"]
```

If you run this code in IRB, you'll see:

```
001:0 > ["Red", "Yellow", "Blue"].each do |color|
?>        puts "There are #{color.length} letters in #{color}"
003:1 > end

There are 3 letters in Red
There are 6 letters in Yellow
There are 4 letters in Blue
=> ["Red", "Yellow", "Blue"]
```

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?`

Imagine wanting to know if all the numbers in an array are odd. You could use each with something like:

```
all_odd = true
[1,2,3].each do |number|
  if number.even? # Will evaluate to false for 1, true for 2, false for 3
    all_odd = false
  end
end
all_odd #=> false
```

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?`:

```
all_odd = [1,3].all? do |number|
  number.odd? # Will evaluate to true for 1, true for 3
end #=> true
all_odd #=> true
```

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.

```
all_odd = [1,2,3].all? do |number|
  number.odd? # Will evaluate to true for 1, false for 2, true for 3
end #=> false
all_odd #=> false
```

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?`

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?`.

```
[1,3].none?{|i| i.even?} #=> true
```

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`:

```
none_even = true
[1,3].each do |i|
  if i.even?
    none_even = false
  end
end #=> [1,3] because `#each` always returns the original collection
none_even #=> true
```

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?`

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.

```
[1,2,100].any?{|i| i > 99} #=> true
```

The `#any?` expression above will return `true` because at least one element, `100`, will produce a `true` evaluation in the block.

## `#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_numbers = [4,8,15,16,23,42]
the_numbers.include?(42)   #=> true
the_numbers.include?(6)   #=> 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.

View [Ruby Boolean Enumerables](https://learn.co/lessons/ruby-boolean-enumerables) on Learn.co and start learning to code for free.
