2016-12-15 74 views
1

如果我使用Ruby普查員來實現發電機和一個過濾器:「破」與在「拋出StopIteration異常」一個Ruby枚舉

generator = Enumerator.new do |y| 
    x = 0 
    loop do 
    y << x 
    x += 1 
    break if x > CUTOFF 
    end 
end.lazy 

filter = Enumerator.new do |y| 
    loop do 
    i = generator.next 
    y << i if i.even? 
    end 
end 

這有什麼區別我是否打破了使用

發電機的循環
break if x > CUTOFF 

VS

raise StopIteration if x > CUTOFF 

兩者都似乎工作。我想break會更高性能,但在這裏更0123是慣用嗎?

+0

斷裂了,因爲你與'lazy'我個人選擇'提高StopIteration'工作的慣用方式。 –

+1

這似乎是使用ruby的一種非常pythonic的方式。根據你正在努力完成的任務,可能有更好的方法來實現它 – Zack

+0

@Zack這個例子不是我真正用例的非常具有代表性的 - 只是一個非常簡單的例子來演示我遇到的問題。真正的生成器進行一系列api調用,批量獲取記錄,每次記錄一條記錄,直到需要獲取另一批記錄爲止。這全部包裹在另一個Enumerator中,用於過濾掉與調用代碼相關的記錄。 – ivan

回答

1

在Ruby中,它是considered a bad practice使用raise/fail控制流,因爲它們真的很慢。

因此,要回答你的問題raise StopIteration if x > CUTOFF是不是從環

+1

Tisk * Tisk,因爲這正是['Enumerator#next'](https://ruby-doc.org/core-2.0.0/Enumerator.html#method-i-next)處理退出循環的方式。 (以及'#peek'和'#next_values'。老實說,我會一直使用'提高StopIteration'來獲取'Kernel#loop'或者'Enumerator',因爲ruby團隊顯然不僅支持這個概念,而且還依賴於它 – engineersmnky

+0

@engineersmnky遺憾的是rails和ruby的舊部分包含了今天不被認爲是習慣用法的代碼。Mike Perham _(sidekiq的創建者)_寫了一篇很棒的文章(http://www.mikeperham.com/2010/) 11/22/the-ruby-stdlib-a-ghetto /)關於它 –

+0

使用大多數「關鍵字」一般來說不是慣用語(break是一個關鍵字)機會有更好的實現'LazyEnumerator'會是我的建議,我認爲如果核心團隊想要修復「StopIteration」的使用,由於其範圍有限,所以它很簡單 – engineersmnky