當前位置: 首頁>>編程示例 >>用法及示例精選 >>正文


Ruby Lazy類用法及代碼示例

本文簡要介紹ruby語言中 Enumerator::Lazy類 的用法。

Enumerator::Lazy Enumerator 的一種特殊類型,它允許在不立即評估它們的情況下構造操作鏈,並在 as-needed 基礎上評估值。為了做到這一點,它重新定義了大多數 Enumerable 方法,以便它們隻是構造另一個惰性枚舉器。

Enumerator::Lazy 可以使用 Enumerable#lazy 方法從任何 Enumerable 構造。

lazy = (1..Float::INFINITY).lazy.select(&:odd?).drop(10).take_while { |i| i < 30 }
# => #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: #<Enumerator::Lazy: 1..Infinity>:select>:drop(10)>:take_while>

當調用任何未重新定義的 Enumerable 方法時執行真正的枚舉,例如 Enumerable#first Enumerable#to_a (後者別名為 force 以獲得更多語義代碼):

lazy.first(2)
#=> [21, 23]

lazy.force
#=> [21, 23, 25, 27, 29]

請注意,大多數 Enumerable 方法可以在有或沒有塊的情況下調用,在 Enumerator::Lazy 上將始終需要一個塊:

[1, 2, 3].map       #=> #<Enumerator: [1, 2, 3]:map>
[1, 2, 3].lazy.map  # ArgumentError: tried to call lazy map without a block

此類允許對長序列或無限序列進行慣用計算,以及在不構造中間數組的情況下鏈接計算。

使用緩慢計算的序列的示例:

require 'open-uri'

# This will fetch all URLs before selecting
# necessary data
URLS.map { |u| JSON.parse(URI.open(u).read) }
  .select { |data| data.key?('stats') }
  .first(5)

# This will fetch URLs one-by-one, only till
# there is enough data to satisfy the condition
URLS.lazy.map { |u| JSON.parse(URI.open(u).read) }
  .select { |data| data.key?('stats') }
  .first(5)

用“.eager” 結束一個鏈會生成一個非惰性枚舉器,它適用於返回或傳遞給另一個需要普通枚舉器的方法。

def active_items
  groups
    .lazy
    .flat_map(&:items)
    .reject(&:disabled)
    .eager
end

# This works lazily; if a checked item is found, it stops
# iteration and does not look into remaining groups.
first_checked = active_items.find(&:checked)

# This returns an array of items like a normal enumerator does.
all_checked = active_items.select(&:checked)

相關用法


注:本文由純淨天空篩選整理自ruby-lang.org大神的英文原創作品 Lazy類。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。