module Enumerable

What’s Here

Module Enumerable provides methods that are useful to a collection class for:

Methods for Querying

These methods return information about the Enumerable other than the elements themselves:

Methods for Fetching

These methods return entries from the Enumerable, without modifying it:

Leading, trailing, or all elements:

Minimum and maximum value elements:

Groups, slices, and partitions:

Methods for Searching and Filtering

These methods return elements that meet a specified criterion:

Methods for Sorting

These methods return elements in sorted order:

Methods for Iterating

Other Methods

Usage

To use module Enumerable in a collection class:

Example:

class Foo
  include Enumerable
  def each
    yield 1
    yield 1, 2
    yield
  end
end
Foo.new.each_entry{ |element| p element }

Output:

1
[1, 2]
nil

Enumerable in Ruby Classes

These Ruby core classes include (or extend) Enumerable:

These Ruby standard library classes include Enumerable:

Virtually all methods in Enumerable call method each in the including class:

About the Examples

The example code snippets for the Enumerable methods:

Extended Methods

A Enumerable class may define extended methods. This section describes the standard behavior of extension methods for reference purposes.

size

Enumerator has a size method. It uses the size function argument passed to Enumerator.new.

e = Enumerator.new(-> { 3 }) {|y| p y; y.yield :a; y.yield :b; y.yield :c; :z }
p e.size #=> 3
p e.next #=> :a
p e.next #=> :b
p e.next #=> :c
begin
  e.next
rescue StopIteration
  p $!.result #=> :z
end

The result of the size function should represent the number of iterations (i.e., the number of times Enumerator::Yielder#yield is called). In the above example, the block calls yield three times, and the size function, +-> { 3 }+, returns 3 accordingly. The result of the size function can be an integer, Float::INFINITY, or nil. An integer means the exact number of times yield will be called, as shown above. Float::INFINITY indicates an infinite number of yield calls. nil means the number of yield calls is difficult or impossible to determine.

Many iteration methods return an Enumerator object with an appropriate size function if no block is given.

Examples:

["a", "b", "c"].each.size #=> 3
{a: "x", b: "y", c: "z"}.each.size #=> 3
(0..20).to_a.permutation.size #=> 51090942171709440000
loop.size #=> Float::INFINITY
(1..100).drop_while.size #=> nil  # size depends on the block's behavior
STDIN.each.size #=> nil # cannot be computed without consuming input
File.open("/etc/resolv.conf").each.size #=> nil # cannot be computed without reading the file

The behavior of size for Range-based enumerators depends on the begin element:

Examples:

(10..42).each.size #=> 33
(10..42.9).each.size #=> 33 (the #end element may be a non-integer numeric)
(10..).each.size #=> Float::INFINITY
("a".."z").each.size #=> nil
("a"..).each.size #=> nil
(1.0..9.0).each.size # raises TypeError (Float does not have #succ)
(..10).each.size # raises TypeError (beginless range has nil as its #begin)

The Enumerable module itself does not define a size method. A class that includes Enumerable may define its own size method. It is recommended that such a size method be consistent with Enumerator#size.

Array and Hash implement size and return values consistent with Enumerator#size. IO and Dir do not define size, which is also consistent because the corresponding enumerator’s size function returns nil.

However, it is not strictly required for a class’s size method to match Enumerator#size. For example, File#size returns the number of bytes in the file, not the number of lines.