Mae向きなブログ

Mae向きな日記のブログ版。ようやくこちらに移行してきました。

Enumerable#lazyメソッドを試してみました

を読みながら復習をしていたのですが、Ruby 2.0で導入されたEnumerable#lazyを試してみたくなったので少し脱線してみました。

    • fibonacci.rb
# -*- coding: utf-8 -*-
class Fibonacci
  include Enumerable
  def each
    return to_enum unless block_given?
    a, b = 0, 1
    loop do
      yield b
      a, b = b, a + b
    end
  end
end

if $0 == __FILE__
  @fib = Fibonacci.new

  puts "(実験:1) フィボナッチ数列の最初10項を得る。"
  # lazy有り、なしに関わらず動作
  p @fib.lazy.first(10)
  p @fib.first(10)

  puts "(実験:2) フィボナッチ数列の第6〜10項を得る。"
  # lazy無しだと無限ループ
  p @fib.lazy.drop(5).first(5)
  # p @fib.drop(5).first(5)

  puts "(実験:3) フィボナッチ数列の100以上1000未満の数値を得る。"
  # lazy無しだと無限ループ
  p @fib.lazy.drop_while{|e| e < 100}.take_while{|e| e < 1000}.to_a
  # p @fib.drop_while{|e| e < 100}.take_while{|e| e < 1000}.to_a
end
    • 実行結果
$ ruby fibonacci.rb
(実験:1) フィボナッチ数列の最初10項を得る。
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
(実験:2) フィボナッチ数列の第6〜10項を得る。
[8, 13, 21, 34, 55]
(実験:3) フィボナッチ数列の100以上1000未満の数値を得る。
[144, 233, 377, 610, 987]

(実験:2)と(実験:3)では、Enumerable#lazyメソッドを付けないと、Enumerable#dropとEnumerable#drop_whileが残りの要素を配列として返そうと無限ループに入ってしまい、いつまでたっても結果が出力されないのだと思います。