Skip to content

Instantly share code, notes, and snippets.

@isaiah
Last active August 29, 2015 14:10
Show Gist options
  • Select an option

  • Save isaiah/3ae573bdfeb75bdd5788 to your computer and use it in GitHub Desktop.

Select an option

Save isaiah/3ae573bdfeb75bdd5788 to your computer and use it in GitHub Desktop.

Revisions

  1. isaiah revised this gist Nov 26, 2014. 1 changed file with 81 additions and 93 deletions.
    174 changes: 81 additions & 93 deletions lazy.rb
    Original file line number Diff line number Diff line change
    @@ -1,117 +1,105 @@
    class Yid
    def initialize(&block)
    # creates a new Fiber to be used as an Yielder
    @yielder = Fiber.new do
    yield Fiber
    raise StopIteration # raise an error if there is no more calls
    end
    end

    def next
    # return the value and wait until the next call
    @yielder.resume
    end
    end


    class Lazy
    def initialize(coll)

    @lazy = Yid.new do |yielder|
    if block_given?
    coll.each do |x|
    yield yielder, x
    end
    else
    coll.each do |x|
    yielder.yield x
    class Enumerator
    class Lazy
    def initialize(coll)

    @lazy = Yid.new do |yielder|
    if block_given?
    coll.each do |x|
    yield yielder, x
    end
    else
    coll.each do |x|
    yielder.yield x
    end
    end
    end
    end
    end

    def each
    loop { yield @lazy.next }
    rescue StopIteration
    end

    def select
    Lazy.new(self) do |yielder, *vals|
    result = yield(*vals)
    puts "select: #{result}"
    yielder.yield(*vals) if result
    def each
    loop { yield @lazy.next }
    rescue StopIteration
    end
    end

    def map
    Lazy.new(self) do |yielder, *vals|
    puts 'map'
    yielder.yield yield(*vals)
    def select
    Lazy.new(self) do |yielder, *vals|
    result = yield(*vals)
    yielder.yield(*vals) if result
    end
    end
    end

    def take(n)
    i = 0
    Lazy.new(self) do |yielder, *vals|
    if i < n
    i += 1
    yielder.yield(*vals)
    else
    raise StopIteration
    def map
    Lazy.new(self) do |yielder, *vals|
    yielder.yield yield(*vals)
    end
    end
    end

    def drop(n)
    i = 0
    Lazy.new(self) do |yielder, *vals|
    puts "drop #{i}"
    if i < n
    i += 1
    else
    yielder.yield(*vals)
    def take(n)
    i = 0
    Lazy.new(self) do |yielder, *vals|
    if i < n
    i += 1
    yielder.yield(*vals)
    else
    raise StopIteration
    end
    end
    end
    end

    def drop_while
    to_drop = true
    Lazy.new(self) do |yielder, *vals|
    puts 'drop_while'
    if to_drop
    result = yield(*vals)
    if !result
    to_drop = false
    def drop(n)
    i = 0
    Lazy.new(self) do |yielder, *vals|
    if i < n
    i += 1
    else
    yielder.yield(*vals)
    end
    end
    end

    def drop_while
    to_drop = true
    Lazy.new(self) do |yielder, *vals|
    if to_drop
    result = yield(*vals)
    if !result
    to_drop = false
    end
    end

    if !to_drop
    yielder.yield(*vals)
    if !to_drop
    yielder.yield(*vals)
    end
    end
    end
    end

    def next
    @lazy.next
    end

    def force
    ret = []
    while val = @lazy.next
    ret << val
    def next
    @lazy.next
    end
    rescue StopIteration
    ret
    end
    end

    coll = 1..100
    def force
    ret = []
    while val = @lazy.next
    ret << val
    end
    rescue StopIteration
    ret
    end

    lazy = Lazy.new(coll)
    s = lazy.select{|x| x.odd?}
    s = s.drop_while{|x| x < 30 }
    s = s.drop(20)
    s = s.map{|x| x.to_s }
    s = s.take(10)
    private
    # kudos http://stackoverflow.com/a/19660333/482757
    class Yid
    def initialize(&block)
    # creates a new Fiber to be used as an Yielder
    @yielder = Fiber.new do
    yield Fiber
    raise StopIteration # raise an error if there is no more calls
    end
    end

    puts s.force
    def next
    # return the value and wait until the next call
    @yielder.resume
    end
    end
    end
    end
  2. isaiah created this gist Nov 26, 2014.
    117 changes: 117 additions & 0 deletions lazy.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,117 @@
    class Yid
    def initialize(&block)
    # creates a new Fiber to be used as an Yielder
    @yielder = Fiber.new do
    yield Fiber
    raise StopIteration # raise an error if there is no more calls
    end
    end

    def next
    # return the value and wait until the next call
    @yielder.resume
    end
    end


    class Lazy
    def initialize(coll)

    @lazy = Yid.new do |yielder|
    if block_given?
    coll.each do |x|
    yield yielder, x
    end
    else
    coll.each do |x|
    yielder.yield x
    end
    end
    end
    end

    def each
    loop { yield @lazy.next }
    rescue StopIteration
    end

    def select
    Lazy.new(self) do |yielder, *vals|
    result = yield(*vals)
    puts "select: #{result}"
    yielder.yield(*vals) if result
    end
    end

    def map
    Lazy.new(self) do |yielder, *vals|
    puts 'map'
    yielder.yield yield(*vals)
    end
    end

    def take(n)
    i = 0
    Lazy.new(self) do |yielder, *vals|
    if i < n
    i += 1
    yielder.yield(*vals)
    else
    raise StopIteration
    end
    end
    end

    def drop(n)
    i = 0
    Lazy.new(self) do |yielder, *vals|
    puts "drop #{i}"
    if i < n
    i += 1
    else
    yielder.yield(*vals)
    end
    end
    end

    def drop_while
    to_drop = true
    Lazy.new(self) do |yielder, *vals|
    puts 'drop_while'
    if to_drop
    result = yield(*vals)
    if !result
    to_drop = false
    end
    end

    if !to_drop
    yielder.yield(*vals)
    end
    end
    end

    def next
    @lazy.next
    end

    def force
    ret = []
    while val = @lazy.next
    ret << val
    end
    rescue StopIteration
    ret
    end
    end

    coll = 1..100

    lazy = Lazy.new(coll)
    s = lazy.select{|x| x.odd?}
    s = s.drop_while{|x| x < 30 }
    s = s.drop(20)
    s = s.map{|x| x.to_s }
    s = s.take(10)

    puts s.force