私は2つの列挙子enum1
とenum2
が遅延的に繰り返される必要があるとします(副作用があるため)。どのようにして第3の列挙子を構成しますかenum3
ここでenum3.each{|x| x}
はとなります。はenum1 + enum2
と等価ですか?2つの他の列挙子を使って遅延を繰り返すルビの列挙子を作るにはどうしたらいいですか?
私の実際の使用例では、2つのファイルにストリーミングしており、連結をストリーミングする必要があります。ここで
私は2つの列挙子enum1
とenum2
が遅延的に繰り返される必要があるとします(副作用があるため)。どのようにして第3の列挙子を構成しますかenum3
ここでenum3.each{|x| x}
はとなります。はenum1 + enum2
と等価ですか?2つの他の列挙子を使って遅延を繰り返すルビの列挙子を作るにはどうしたらいいですか?
私の実際の使用例では、2つのファイルにストリーミングしており、連結をストリーミングする必要があります。ここで
これは、ように見えますちょうど私がしたい方法で働く;
enums.lazy.flat_map{|enum| enum.lazy }
ここにデモンストレーションがあります。これらの降伏方法を副作用で定義する。
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 }
次に、副作用が遅延していることを示す結果を次に呼び出します。
[5] pry(main)> concated_enum.next
hi
=> 1
[6] pry(main)> concated_enum.next
hi again
=> 2
はでスロー怠惰な列挙といくつかのcode I wrote for fun awhile backです:
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 }
'flat_map'ソリューションに感謝します。 flat_mapの怠惰をすでに確認したにもかかわらず、これは私たちには発生せず、怠け者の追加として使用することができました! :) –
このソリューションの欠点は、 'concated_enum.size'は常に' nil'を返すことです。 – skalee
@skalee私はそれが怠惰なenumの欠点だと思う。あなたがそれらを反復するまで、あなたはどれくらいの大きさであるかを決して知ることはできません。それらのサイズは、あなたが反復するのにかかる時間の関数であるかもしれません。彼らは無限でもあります。 –