# class Enumerator::Product

`Enumerator::Product` generates a Cartesian product of any number of enumerable objects. Iterating over the product of enumerable objects is roughly equivalent to nested each_entry loops where the loop for the rightmost object is put innermost.

    innings = Enumerator::Product.new(1..9, ['top', 'bottom'])

    innings.each do |i, h|
      p [i, h]
    end
    # [1, "top"]
    # [1, "bottom"]
    # [2, "top"]
    # [2, "bottom"]
    # [3, "top"]
    # [3, "bottom"]
    # ...
    # [9, "top"]
    # [9, "bottom"]

The method used against each enumerable object is ‘each_entry` instead of `each` so that the product of N enumerable objects yields an array of exactly N elements in each iteration.

When no enumerator is given, it calls a given block once yielding an empty argument list.

This type of objects can be created by `Enumerator.product`.

### Public Class Methods

Enumerator::Product.new(*enums) → enum click to toggle source

Generates a new enumerator object that generates a Cartesian product of given enumerable objects.

    e = Enumerator::Product.new(1..3, [4, 5])
    e.to_a #=> [[1, 4], [1, 5], [2, 4], [2, 5], [3, 4], [3, 5]]
    e.size #=> 6

    static VALUE
    enum_product_initialize(int argc, VALUE *argv, VALUE obj)
    {
        struct enum_product *ptr;
        VALUE enums = Qnil, options = Qnil;

        rb_scan_args(argc, argv, "*:", &enums, &options);

        if (!NIL_P(options) && !RHASH_EMPTY_P(options)) {
            rb_exc_raise(rb_keyword_error_new("unknown", rb_hash_keys(options)));
        }

        rb_check_frozen(obj);
        TypedData_Get_Struct(obj, struct enum_product, &enum_product_data_type, ptr);

        if (!ptr) rb_raise(rb_eArgError, "unallocated product");

        ptr->enums = rb_obj_freeze(enums);

        return obj;
    }

### Public Instance Methods

each { |...| ... } → obj click to toggle source
each → enumerator

Iterates over the elements of the first enumerable by calling the “each_entry” method on it with the given arguments, then proceeds to the following enumerables in sequence until all of the enumerables are exhausted.

If no block is given, returns an enumerator. Otherwise, returns self.

    static VALUE
    enum_product_each(VALUE obj)
    {
        RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_product_enum_size);

        return enum_product_run(obj, rb_block_proc());
    }

inspect → string click to toggle source

Returns a printable version of the product enumerator.

    static VALUE
    enum_product_inspect(VALUE obj)
    {
        return rb_exec_recursive(inspect_enum_product, obj, 0);
    }

rewind → obj click to toggle source

Rewinds the product enumerator by calling the “rewind” method on each enumerable in reverse order. Each call is performed only if the enumerable responds to the method.

    static VALUE
    enum_product_rewind(VALUE obj)
    {
        struct enum_product *ptr = enum_product_ptr(obj);
        VALUE enums = ptr->enums;
        long i;

        for (i = 0; i < RARRAY_LEN(enums); i++) {
            rb_check_funcall(RARRAY_AREF(enums, i), id_rewind, 0, 0);
        }

        return obj;
    }

size → int, Float::INFINITY or nil click to toggle source

Returns the total size of the enumerator product calculated by multiplying the sizes of enumerables in the product. If any of the enumerables reports its size as nil or Float::INFINITY, that value is returned as the size.

    static VALUE
    enum_product_size(VALUE obj)
    {
        return enum_product_total_size(enum_product_ptr(obj)->enums);
    }