比方說,我有兩個普查員,enum1
和enum2
,必須懶惰地迭代(因爲他們有副作用)。我如何構造第三個枚舉器enum3
其中enum3.each{|x| x}
會懶洋洋地返回相當於enum1 + enum2
?我該如何製作一個通過兩個其他枚舉器進行延遲迭代的ruby枚舉器?
在我真實世界的用例中,我在兩個文件中進行流式處理,並且需要流出並置。
比方說,我有兩個普查員,enum1
和enum2
,必須懶惰地迭代(因爲他們有副作用)。我如何構造第三個枚舉器enum3
其中enum3.each{|x| x}
會懶洋洋地返回相當於enum1 + enum2
?我該如何製作一個通過兩個其他枚舉器進行延遲迭代的ruby枚舉器?
在我真實世界的用例中,我在兩個文件中進行流式處理,並且需要流出並置。
這似乎按照我想要的方式工作;
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我認爲這是懶惰枚舉的缺點;除非你重複它們,否則你永遠不會知道它們有多大。它們的大小可能是你迭代多長時間的函數。他們甚至可以是無限的。 –