Monday, November 5, 2012

Ruby 2.0 new feature : Enumerator::Lazy

In functional language, The feature called "lazy evaluation" exists as its key feature. For example, fibonacci in F# is:
Microsoft (R) F# Interactive version 11.0.50727.1
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

> let fibonacci = Seq.cache <| Seq.unfold (fun (current, next) -> Some(current, (next, current + next))) (0I, 1I);;

val fibonacci : seq

> fibonacci |> Seq.nth 100;;
val it : System.Numerics.BigInteger =
  354224848179261915075 {IsEven = false;
                         IsOne = false;
                         IsPowerOfTwo = false;
                         IsZero = false;
                         Sign = 1;}

Ruby 2.0's Enumerator::Lazy can do "lazy evaluation" like this:
irb(main):001:0> RUBY_VERSION
=> "2.0.0"
irb(main):002:0> fibonacci = Enumerator.new { |y|
irb(main):003:1*   a = 0
irb(main):004:1*   b = 1
irb(main):005:1>   loop do
irb(main):006:2*     y << a
irb(main):007:2>     a, b = b, a + b
irb(main):008:2>   end
irb(main):009:1> }.lazy
=> #<Enumerator::Lazy: #<Enumerator: #<Enumerator::Generator:0x23cbbc0>:each>>
irb(main):010:0> def fibonacci.nth(n)
irb(main):011:1>   self.take(n+1).find.with_index { |elem, i| i == n }
irb(main):012:1> end
=> nil
irb(main):013:0> fibonacci.nth(100)
=> 354224848179261915075

If the above sample did not use Enumerator::Lazy, it would take many many seconds.

No comments:

Post a Comment