Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Enumerator::Lazy

 Enumerator::Lazy

Presented at SF.rb on August 2, 2016.

1f74b13f1e5c6c69cb5d7fbaabb1e2cb?s=128

Erik Berlin

August 02, 2016
Tweet

Transcript

  1. Enumerator::Lazy Erik Michaels-Ober @sferik

  2. Imperative languages
 do iteration like this: int sum = 0;

    for(i = 1; i < 10; i = i + 1) { sum = sum + i; }
  3. Functional languages
 do iteration like this: rec_sum [] = 0

    rec_sum (x:xs) = x + rec_sum xs rec_sum [1..9]
  4. Object oriented languages
 (should) do iteration like this: sum =

    0 (1..9).each do |i| sum += i end
  5. Object oriented languages
 (should) do iteration like this: sum =

    (1..9).inject(&:+)
  6. Iterators Introduced in CLU by
 Barbara Liskov (1975) Copied in

    Ruby by Yukihiro Matsumoto (1995)
  7. Ruby’s iterator is called Enumerator

  8. enum = Enumerator.new do |yielder| yielder.yield("sf") yielder.yield("dot") yielder.yield("rb") end

  9. ["sf", "dot", "rb"].each ["sf", "dot", "rb"].to_enum Enumerator.new(["sf", "dot", "rb"])

  10. enum = Enumerator.new do |yielder| n = 0 loop do

    yielder.yield(n) n += 1 end end
  11. fib = Enumerator.new do |yielder| a = b = 1

    loop do yielder.yield(a) a, b = b, a + b end end
  12. module Enumerable def lazy_map(&block) Enumerator.new do |yielder| return to_enum(__method__) unless

    block_given? each do |n| yielder.yield(block.call(n)) end end end end
  13. module Enumerable def lazy_select(&block) Enumerator.new do |yielder| return to_enum(__method__) unless

    block_given? each do |n| yielder.yield(n) if block.call(n) end end end end
  14. Ruby 2.0 introduced Enumerator::Lazy

  15. What are the first five even perfect squares over a

    thousand?
  16. lazy_integers = (1..Float::INFINITY).lazy lazy_integers.collect { |x| x ** 2 }.

    select { |x| x.even? }. reject { |x| x < 1000 }. first(5) #=> [1024, 1156, 1296, 1444, 1600]
  17. What are the first five
 twin primes?

  18. require "prime" lazy_primes = Prime.lazy lazy_primes.select { |x| (x -

    2).prime? }. collect { |x| [x - 2, x] }. first(5) #=> [[3, 5], [5, 7], [11, 13], [17, 19], [29, 31]]
  19. module Enumerable def repeat_after_first return to_enum(__method__) unless block_given? each.with_index do

    |*val, index| index.zero? ? yield(*val) : 2.times { yield(*val) } end end end
  20. require "prime" lazy_primes = Prime.lazy lazy_primes.repeat_after_first. each_slice(2). select { |x,

    y| x + 2 == y }. first(5) #=> [[3, 5], [5, 7], [11, 13], [17, 19], [29, 31]]
  21. When are the next five
 Friday the 13ths?

  22. require "date" lazy_dates = (Date.today..Date.new(9999)).lazy lazy_dates.select { |d| d.day ==

    13 }. select { |d| d.friday? }. first(10)
  23. Detect whether a text file contains a string? (without reading

    the entire file into memory)
  24. lazy_file = File.readlines("/path/to/file").lazy lazy_file.detect { |x| x =~ /regexp/ }

  25. Being lazy is efficient.

  26. Being lazy is elegant.

  27. None
  28. Thank you