From: knu@... Date: 2018-11-21T06:26:52+00:00 Subject: [ruby-core:89916] [Ruby trunk Feature#15144] Enumerator#chain Issue #15144 has been updated by knu (Akinori MUSHA). File 0001-Implement-Enumerator-Chain-and-Enumerator-chain-Feat.patch added I've written an initial implementation as attached: - `Enumerator.chain(*enums)` to generate an enumerator chain of `enums` - `Enumerator#+(other)` to generate an enumerator chain of `[self, other]` - `Enumerator#chain(*others)` to generate an enumerator chain of `[self, *others]` Some notes: - The constructor is currently `Enumerator::Chain.new(*enums)` but it should probably be `Enumerator::Chain.new(enums)` to make it extensible to take an enumerable in general, with `itertools.chain.from_iterable` of Python in mind. - `Enumerator.chain(Enumerator.chain(e1, e2), e3)` cannot be optimized to `Enumerator.chain(e1, e2, e3)` because it is expected that the intermediate object `Enumerator.chain(e1, e2)` is expected to receive a call for `each` when `Enumerator.chain(Enumerator.chain(e1, e2), e3).each {���}` is called. ---------------------------------------- Feature #15144: Enumerator#chain https://bugs.ruby-lang.org/issues/15144#change-74999 * Author: zverok (Victor Shepelev) * Status: Assigned * Priority: Normal * Assignee: matz (Yukihiro Matsumoto) * Target version: ---------------------------------------- I am not sure I am not missing something, but... ```ruby [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... ```ruby # 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: ```ruby 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-------------------------------- 0001-Implement-Enumerator-Chain-and-Enumerator-chain-Feat.patch (13.3 KB) -- https://bugs.ruby-lang.org/ Unsubscribe: