Lazy Enumerators

Каждый раз, когда используются такие методы, как map, collect, select и тд - создаётся перечислитель. Благодаря перечислителям методы можно объединять в цепочки, например:

[1, 2, 3].map { .... }.select { .... }

Вызов методов each или select возвращает перечислитель, как показано ниже:

[1, 2, 3].each
=> #<Enumerator: ...>

[1, 2, 3].select
=> #<Enumerator: ...>

К примеру, нужно получить 10 профилей пользователей Twitter, у которых в биографии профиля есть @rails. Предположим, есть 1000 идентификаторов пользователей Twitter. Можно использовать следующий подход для получения 10 пользователей:

# Array of twitter user id's
twitter_user_ids = [...]

twitter_user_ids.map { |user_id| TwitterClient.user(user_id) }
.select { |data| data[:description].includes?("@rails") }
.first(10)

Происходит обработка всех 1000 пользователей, даже если у первых 10 пользователей в биографии был @rails.


Ленивый перечислитель позволяет получить пользователей по одному, не перебирая всех 1000 пользователей одновременно. Цикл завершается, когда получено 10 пользователей, соответствующих требуемому условию.

# Array of twitter user id's
twitter_user_ids = [...]

twitter_user_ids.lazy
.map { |user_id| TwitterClient.user(user_id) }
.select { |data| data[:description].includes?("@rails") }
.first(10)