ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: "knu (Akinori MUSHA)" <noreply@ruby-lang.org>
To: ruby-core@ruby-lang.org
Subject: [ruby-core:108335] [Ruby master Feature#18685] Enumerator.product: Cartesian product of enumerables
Date: Thu, 21 Apr 2022 08:04:55 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-97360.20220421080454.8@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-18685.20220408072029.8@ruby-lang.org

Issue #18685 has been updated by knu (Akinori MUSHA).


Thanks.  Performance monsters can also special-case arrays and ranges and omit calls to each_entry to boost performance. 😂

----------------------------------------
Feature #18685: Enumerator.product: Cartesian product of enumerables
https://bugs.ruby-lang.org/issues/18685#change-97360

* Author: knu (Akinori MUSHA)
* Status: Open
* Priority: Normal
* Target version: 3.2
----------------------------------------
I'd like to add a new Enumerator class method for generating the Cartesian product of given enumerators.
A product here does not mean an accumulated array of arrays, but an enumerator to enumerate all combinations.

```ruby
product = Enumerator.product(1..3, ["A", "B"])
p product.class #=> Enumerator

product.each do |i, c|
  puts "#{i}-#{c}"
end

=begin output
1-A
1-B
2-A
2-B
3-A
3-B
=end
```

This can be used to reduce nested blocks and allows for iterating over an indefinite number of enumerable objects.

## Implementation notes

- It should internally use `each_entry` instead of `each` on enumerable objects to make sure to capture all yielded arguments.
- If no enumerable object is given, the block is called once with no argument.
- It should reject a keyword-style hash argument so we can add keyword arguments in the future without breaking existing code.
- Here's an example implementation:

  ```ruby
  # call-seq:
  #   Enumerator.product(*enums)                   -> enum
  #   Enumerator.product(*enums) { |*args| block } -> return value of args[0].each_entry {}
  def Enumerator.product(*enums, **nil, &block)
   # TODO: size should be calculated if possible
    return to_enum(__method__, *enums) if block.nil?

    enums.reverse.reduce(block) { |inner, enum|
      ->(*values) {
        enum.each_entry { |value|
          inner.call(*values, value)
        }
      }
    }.call()
  end
  ```

- Not to be confused with `Enumerator.produce`. 😝

## Prior case
- Python: https://docs.python.org/3/library/itertools.html#itertools.product




-- 
https://bugs.ruby-lang.org/

  parent reply	other threads:[~2022-04-21  8:05 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-08  7:20 [ruby-core:108198] [Ruby master Feature#18685] Enumerator.product: Cartesian product of enumerators knu (Akinori MUSHA)
2022-04-08 10:52 ` [ruby-core:108199] [Ruby master Feature#18685] Enumerator.product: Cartesian product of enumerables Eregon (Benoit Daloze)
2022-04-21  7:59 ` [ruby-core:108334] " matz (Yukihiro Matsumoto)
2022-04-21  8:04 ` knu (Akinori MUSHA) [this message]
2022-04-21 10:37 ` [ruby-core:108346] " Eregon (Benoit Daloze)
2022-04-21 10:40 ` [ruby-core:108347] " Eregon (Benoit Daloze)
2022-04-23 19:26 ` [ruby-core:108387] " shan (Shannon Skipper)
2022-04-24  2:36 ` [ruby-core:108388] " knu (Akinori MUSHA)
2022-04-26  7:02 ` [ruby-core:108405] " sawa (Tsuyoshi Sawada)
2022-07-29  8:29 ` [ruby-core:109362] " knu (Akinori MUSHA)
2022-11-17  6:42 ` [ruby-core:110790] " hsbt (Hiroshi SHIBATA)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.ruby-lang.org/en/community/mailing-lists/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-97360.20220421080454.8@ruby-lang.org \
    --to=ruby-core@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).