I want to connect two Ruby enumerators. Give me all the values from the first, then the second, and so on. Ideally, without forcing any lazy evaluations and flat so I don’t have to think about nested stuff. Like so:
xs = [1, 2, 3].to_enum ys = [4, 5, 6].to_enum [xs, ys].chain.to_a # => [1, 2, 3, 4, 5, 6]
I couldn’t figure out how to do that with Ruby’s standard library alone. But, it wasn’t that hard to write my own:
def chain(*enums) return to_enum(:chain, *enums) unless block_given? enums.each { |enum| enum.each { |e| yield e } } end
But it seems like Ruby’s library, Enumerable
in particular, is so strong I must have missed something. So, mob programmers, is there a better way to do this? A fancier enumerator-combining thing I’m missing?
Hey, Adam, that’s an interesting problem!
It seems like you need a lazy enumerator that can abstract multiple enumerables into a single enumerator that lazily provides items from each enumerable, on demand.
Let me know if this would do the trick: https://github.com/drborges/ruby-spikes/blob/master/lazy_enumerator.rb
Cheers.
I’m not sure if you would like to avoid using lazy or avoid evaluating anything lazy. If the latter then this might work:
ns = [xs, ys].lazy.flat_map(&:lazy)
=> #
ns.force
=> [1, 2, 3, 4, 5, 6]
Well, that first row would have returned an Enumerator::Lazy if it hadn’t been eaten by the comment system.