How can I make a ruby ​​enumerator that does lazy iteration through two other counters?

Let's say I have two counters, enum1and enum2that should be lazily repeated (because they have side effects). How to create a third counter enum3where enum3.each{|x| x}lazily returns the equivalent enum1 + enum2?

In my use case in the real world, I am streaming in two files and need to stream from concatenation.

+4
source share
2 answers

It is like the way I want;

enums.lazy.flat_map{|enum| enum.lazy }

Here is a demo. Identify these inferior methods with side effects;

def test_enum
  return enum_for __method__ unless block_given?
  puts 'hi'
  yield 1
  puts 'hi again'
  yield 2
end  

def test_enum2
  return enum_for __method__ unless block_given?
  puts :a
  yield :a
  puts :b
  yield :b
end  

concated_enum = [test_enum, test_enum2].lazy.flat_map{|en| en.lazy }

Then call the following result, showing that side effects occur lazily;

[5] pry(main)> concated_enum.next
hi
=> 1
[6] pry(main)> concated_enum.next
hi again
=> 2
+5

, , :

def cat(*args)
  args = args.to_enum

  Enumerator.new do |yielder|
    enum = args.next.lazy

    loop do
      begin
        yielder << enum.next
      rescue StopIteration
        enum = args.next.lazy
      end
    end
  end
end

:

enum1 = [1,2,3]
enum2 = [4,5,6]
enum3 = cat(enum1, enum2)

enum3.each do |n|
  puts n
end
# => 1
#    2
#    3
#    4
#    5
#    6

... :

cat([1,2,3],[4,5,6]).each {|n| puts n }
0

Source: https://habr.com/ru/post/1650718/


All Articles