Project

General

Profile

Actions

Feature #15144

closed

Enumerator#chain

Added by zverok (Victor Shepelev) almost 4 years ago. Updated over 3 years ago.

Status:
Closed
Priority:
Normal
Target version:
-
[ruby-core:89121]

Description

I am not sure I am not missing something, but...

[1, 2, 3].each.chain([3, 4, 5].each) # => Enumerator

...seem to be a useful pattern.

It especially shows itself in case of lazy enumerators, representing several long-calculated sequences, like something...

# just data from several sources, abstracted into enumerator, fetching it on demand
process = URLS.lazy.map(&Faraday.method(:get)))
  .chain(LOCAL_FILES.lazy.map(&File.method(:read)))
  .chain(FALLBACK_FILE.then.lazy.map(&File.method(:read))) # with yield_self aka then we can even chain ONE value

process.detect { |val| found?(val) } # uniformely search several sources (lazy-loading them) for some value

# tty-progressbar is able to work with enumerables:
bar = TTY::ProgressBar.new("[:bar]", total: URLS.count + LOCAL_FILES.count + 1)
bar.iterate(process).detect { |val| found?(val) } # shows progress-bar for uniform process of detection

Prototype impl. is dead simple, of course:

class Enumerator
  def chain(*others)
    Enumerator.new { |y|
      [self, *others].each { |e| e.each { |v| y << v } }
    }
  end
end

Obviously, the effect could be reached with flat_map, but it seems "chaining" of iterations is pretty common and clear concept (and Google search for "ruby enumerator chain" shows people constantly ask about the way).


Files


Related issues 1 (0 open1 closed)

Related to Ruby master - Feature #709: Enumerator#+Rejectedknu (Akinori MUSHA)Actions
Actions

Also available in: Atom PDF