Lazy evaluation of infinite enumerator in Ruby 1.9 - calling instance method on object from different class -


i'm trying grips lazy evaluation of enumerator using ruby 1.9. work in progress have other bugs/missing code have 1 specific problem right now. i'm trying pass test (note cannot change test):

def test_enumerating_with_a_single_enumerator   enumerator = someclass.new(some_infinite_sequence.to_enum)   assert_equal [1, 2, 3, 4, 5], enumerator.take(5) end 

i've written code below , know problem i'm calling lazy_select instance method someclass on argument initialize method instance of enumerator class, nomethoderror. suggestions? thank you.

class someclass < enumerator    def initialize(*enumerators)     super() |yielder|       enumerators.each |enumerator|         enumerator.lazy_select { |yielder, first_value, second_value| yielder.yield first_value if (first_value <=> second_value) <= 0 }         .first(20)       end     end   end    def lazy_select(&block)     self.class.new |yielder|       each_cons(2) |first_value, second_value|         block.call(yielder, first_value, second_value)       end     end   end end 

i have 1 specific problem right now. i'm trying pass test (note cannot change test):

def test_enumerating_with_a_single_enumerator   enumerator = someclass.new(some_infinite_sequence.to_enum)   assert_equal [1, 2, 3, 4, 5], enumerator.take(5) end 
class someclass < enumerator    def initialize(enum, &block)     super() |y|       begin         enum.each |val|           if block             block.call(y, val)  #while initializing sc2 in line b execution takes branch           else             y << val  #while initializing sc1 line execution halts here           end                  end       rescue stopiteration       end      end   end    def lazy_take(n)     taken = 0      someclass.new(self) |y, val|  #line b       if taken < n         y << val         taken += 1       else         raise stopiteration       end     end   end    def take(n)     lazy_take(n).to_a   end end  sc1 = someclass.new( (1..6).cycle )   #line p sc1.take(10)  --output:-- [1, 2, 3, 4, 5, 6, 1, 2, 3, 4] 

sc2 name i'm giving anonymous instance created inside lazy_take().

the code difficult understand. code sets things sc1's enumerator cycle, , sc2's enumerator sc1 (initialize() requires first arg enumerator). when sc1 initialized, code starts stepping through values in cycle , halts @ line:

y << val 

then when lazy_take() called, sc2 created, , initialization code starts stepping through values in sc1. there no values in sc1, sc1 executes line:

y << val 

to inject value cycle sc1's yielder. sc1's yielder yields val sc2--because in sc2's code each() method demanding value sc1. sc2 takes val , injects sc2's yielder. next iteration of each block in sc2 takes place, , once again sc2's code demands value sc1. sc2 repeatedly demands value sc1, causes sc1 pass on value retrieved cycle. once sc2 runs loop n times, stops demanding values sc1. next step make sc2 give values in it's yielder.

if prefer, can define initialize() this:

def initialize(enum)     super() |y|       begin         enum.each |val|           if block_given?             yield y, val  #while initializing sc2 in line b execution takes branch           else             y << val  #while initializing sc1 line execution halts here           end                  end       rescue stopiteration       end      end   end 

that shows not have specify block parameter , explicitly call() block. instead, can dispense block parameter , call yield(), , values sent block automatically.


Comments

Popular posts from this blog

matlab - Deleting rows with specific rules -

php - MySQLi multi_query results for later use -