Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- require "fiber"
- class LazyArray
- attr_accessor :fs
- protected :fs
- @@ENDMARK = Object.new
- def LazyArray.[](*args)
- args.inject(LazyArray.new){|a, b| a.push b }
- end
- def initialize(n = 0)
- @a = []
- @fs = []
- n.times{|i| self.concat yield i }
- end
- def [](idx)
- case idx
- when Range
- xs = LazyArray.new
- xs.fs.push(Fiber.new do
- i = idx.first
- if idx.last >= 0
- l = idx.last
- d = 0
- else
- l = 1 / 0.0
- d = -idx.last
- end
- while i <= l && (self.inbound? i + d)
- Fiber.yield self[i]
- i += 1
- end
- @@ENDMARK
- end)
- xs
- when Integer
- until @a.size > idx || @fs.empty?
- self.progress
- end
- @a[idx]
- end
- end
- def progress
- o = @fs.first.resume
- if o == @@ENDMARK
- @fs.shift
- else
- @a.push o
- end
- end
- def concat(o)
- o
- case o
- when LazyArray
- @fs.push(Fiber.new do
- o.each{|i| Fiber.yield i }
- @@ENDMARK
- end)
- when Enumerable
- @fs.push(Fiber.new do
- o.each{|i| Fiber.yield i }
- @@ENDMARK
- end)
- else
- raise TypeError.new
- end
- self
- end
- def +(o)
- self.clone.concat(o)
- end
- def push(o)
- @fs.push(Fiber.new do
- Fiber.yield o
- @@ENDMARK
- end)
- self
- end
- def inbound?(idx)
- self[idx]
- if @fs.empty?
- idx < @a.size
- else
- true
- end
- end
- def size
- self.progress until @fs.empty?
- @a.size
- end
- def zip(other)
- xs = LazyArray.new
- xs.fs.push(Fiber.new do
- i = 0
- self.each do |a|
- Fiber.yield [a, other[i]]
- i += 1
- end
- @@ENDMARK
- end)
- xs
- end
- def map
- xs = LazyArray.new
- xs.fs.push(Fiber.new do
- self.each{|i| Fiber.yield yield i }
- @@ENDMARK
- end)
- xs
- end
- def select
- xs = LazyArray.new
- xs.fs.push(Fiber.new do
- self.each{|i| Fiber.yield i if yield i }
- @@ENDMARK
- end)
- xs
- end
- def each
- i = 0
- while self.inbound? i
- yield self[i]
- i += 1
- end
- end
- def to_a
- i = @a.size
- while self.inbound? i
- i += 1
- end
- @a.clone
- end
- end
- fib = LazyArray.new.tap{|fib| fib + [0, 1] + fib.zip(fib[1..(1/0.0)]).map{|a, b| a + b } }
- p fib.select{|i| i % 7 == 0 }[0..4].to_a #=> [0, 21, 987, 46368, 2178309]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement