skip to content

In Ruby, what do any?, all?, none? and one? return on an empty collection, and what changes when you pass them a pattern?

level: middleimportance: must knowfreq 55%

answer

  1. vacuous truth on empty
  2. [].all? is true
  3. no block: element truthiness
  4. pattern === element
  5. include? uses ==, not ===

basics

~20 s

On an empty collection all? and none? return true; any? and one? return false. A pattern argument tests pattern === element, so classes, ranges and regexps work, and a block passed alongside is ignored with a warning.

solid answer

~40 s

The four predicates return `true` or `false`. On an empty collection `all?` and `none?` are `true` and `any?` and `one?` are `false`, which is why `invoices.all?(&:paid?)` reports "all paid" when there are no invoices. Without a block or argument they test the elements' own truthiness, so `[nil, false].any?` is `false`. With a **pattern** argument they test `pattern === element`: `days.any?(31..)`, `rows.all?(Invoice)`, `refs.none?(/DRAFT/)`. A block given together with a pattern is ignored and Ruby warns "given block not used". `any?`, `all?` and `none?` stop at the first element that decides the answer; `one?` stops at the second match. Unlike the patterns, `include?` and `count(obj)` compare with `==`.

code

ruby · 17 lines
ruby
days_late = [0, 12, 45]

days_late.any?(31..)          # => true   (Range#===)
days_late.all?(Integer)       # => true   (Module#===)
days_late.none? { |d| d > 90 } # => true
days_late.one?(0)             # => true   (exactly one element == 0)

[].all? { |inv| inv.paid? }   # => true, block never runs
[].any?                       # => false
[nil, false].any?             # => false

[30, 45.5].include?(Integer)  # => false (== comparison)
[30, 45.5].any?(Integer)      # => true  (=== comparison)

days_late.any?(31..) { |d| d > 5 }
# warning: given block not used
# => true

go deeper

for a junior

Recall what each predicate asks and that [].all? is true while [].any? is false.

for a middle

Explain the three forms, that a pattern argument uses ===, the ignored-block warning, and why include? and count(obj) use == instead.

for a senior

Catch vacuous-truth bugs where an empty list passes an all? check, and prefer predicates that exit early over select followed by any?.

for a principal

Push for explicit handling of empty inputs in business rules, since an all? over nothing silently becomes an approval.

## Four yes-or-no questions Ruby's `Enumerable` module, which `Array` also overrides natively, has four **predicate** methods. Each returns `true` or `false` and nothing else: | Method | Question it answers | Empty collection | |---|---|---| | `any?` | does at least one element match? | `false` | | `all?` | does every element match? | `true` | | `none?` | does no element match? | `true` | | `one?` | does exactly one element match? | `false` | The rdoc in Ruby's `enum.c` states the empty cases explicitly: for an empty receiver `all?` returns `true` and `any?` returns `false`, and the argument or block is not used. ## Why `[].all?` is true This is **vacuous truth**: there is no element that fails the test, so "every element passes" holds. It is logically sound and practically dangerous: 1. An accounts-receivable job checks `customer.invoices.all?(&:paid?)` before closing an account. 2. A customer whose invoices failed to load has an empty list. 3. The check passes, and the account is closed as settled. The fix is to state the real requirement: `invoices.any? && invoices.all?(&:paid?)`, or to treat an empty list as its own case before asking. ## Three ways to state the test Each predicate accepts one of three forms: - **No block, no argument**: tests each element's own truthiness. `[nil, 45].any?` is `true`; `[nil, false].any?` is `false`; `[nil, 45, nil].one?` is `true`. - **A block**: tests the block's return value for each element, e.g. `invoices.any? { |i| i.days_late > 30 }`. - **A pattern argument**: tests `pattern === element`. Because `===` is defined by the pattern's class, this covers several cases in one form: - a **class**: `rows.all?(Invoice)` checks types; - a **range**: `days.any?(31..)` checks bounds; - a **regexp**: `refs.none?(/DRAFT/)` checks text; - a plain **value**: `statuses.one?(:disputed)` checks equality. If you pass both a pattern and a block, the pattern wins, the block is ignored, and Ruby emits the warning `given block not used`. ## Early exit The predicates stop as soon as the answer is known: - `any?` stops at the first match; `all?` at the first failure; `none?` at the first match. - `one?` has to keep going after the first match, because a second one changes the answer; it stops at the second. That matters when the block is expensive or has side effects, and it is the main reason to write `invoices.any? { ... }` rather than `invoices.select { ... }.any?`, which evaluates the block for every element first. ## `include?` and `count` compare differently Two neighbouring methods look like predicates but use **`==`**, not `===`: - `include?(obj)`, also called `member?`, returns whether any element `== obj`. - `count(obj)` returns how many elements `== obj`; `count` with a block counts truthy block results, and plain `count` counts everything. So `[30, 45.5].include?(Integer)` is `false`, because no element equals the class `Integer`, while `[30, 45.5].any?(Integer)` is `true`. Mixing the two up is a common interview slip. ## Reading predicate code The four methods are related, and code often mixes them in ways that are easy to misread: - `none? { ... }` is the same as `!any? { ... }`, and reads better than the negation. - `all? { |i| !i.paid? }` is the same as `none?(&:paid?)`; the second form states the intent directly. - `any?` with no block is sometimes used as "not empty", but it means "has a truthy element": `[nil].any?` is `false` although the array has one element. `empty?` is the size question. Preferring the positive form and the pattern argument where they fit keeps business rules readable, which matters when those rules decide who gets a reminder letter. ## `one?` versus "exactly one element" `one?` counts **matches**, not elements. `[nil, 45, nil].one?` is `true` because exactly one element is truthy, and `[45, 60].one?` is `false` because two are. To ask whether a collection has a single element, compare its size instead. ## What a strong answer covers Give the empty-collection table first, including why `all?` is `true`. Then name the three forms, the `===` semantics of the pattern argument, the ignored block warning, and early exit. Finish by contrasting `include?` and `count(obj)`, which use `==`.

  • How would you guard an all? check against an empty list?
    Make the non-empty requirement explicit: `invoices.any? && invoices.all?(&:paid?)`, or handle `invoices.empty?` first with its own outcome. `all?` on an empty collection is `true` by definition, so the check alone cannot tell "all paid" from "nothing loaded".
  • Why does [30, 45.5].include?(Integer) return false while any?(Integer) returns true?
    `include?` asks whether any element `== Integer`, and neither 30 nor 45.5 equals the class object. `any?(Integer)` asks whether `Integer === element` for any element, and `Module#===` checks class membership, which 30 satisfies. `count(obj)` uses `==` too.
  • When does one? stop iterating?
    At the second match. After one match it cannot yet answer, because another match would make the result `false`; once a second match appears it returns `false` immediately. If it reaches the end with exactly one match, it returns `true`.

saying these in an interview costs you the question

  • all? on an empty collection returns false because nothing was checked
  • any? with a pattern compares elements with ==
  • Passing both a pattern and a block combines the two tests
  • one? returns true when the collection has exactly one element
  • include?(Integer) checks whether any element is an Integer