Returns a lazy list which is generated from the Enumerable a or LazyList.span(a, n), if n was given as an argument.
# File lib/lazylist.rb, line 189 def self.[](a, n = nil) case when n span(a, n) when a.respond_to?(:to_io) io(a.to_io) when a.respond_to?(:to_ary) from_queue(a.to_ary) when Range === a from_range(a) when a.respond_to?(:each) from_enum(a) else list(a) end end
If the constant Empty is requested return a new empty list object.
# File lib/lazylist.rb, line 134 def self.const_missing(id) if id == :Empty new(nil, nil) else super end end
Returns an empty list.
# File lib/lazylist.rb, line 94 def self.empty new(nil, nil) end
Returns a list of all elements succeeding n (that is created by calling the succ method) and starting from n.
# File lib/lazylist.rb, line 259 def self.from(n = 0) tabulate(n) end
Generates a lazy list from any data structure e which responds to the each method.
# File lib/lazylist.rb, line 208 def self.from_enum(e) from_queue ReadQueue.new(e) end
Generates a lazyx list by popping elements from a queue.
# File lib/lazylist.rb, line 213 def self.from_queue(rq) return empty if rq.empty? new(delay { rq.shift }) { from_queue(rq) } end
Generates a lazy list from a Range instance r.
# File lib/lazylist.rb, line 219 def self.from_range(r) if r.exclude_end? if r.begin >= r.end empty else new(delay { r.begin }) { from_range(r.begin.succ...r.end) } end else case when r.begin > r.end empty when r.begin == r.end new(delay { r.begin }) { empty } else new(delay { r.begin }) { from_range(r.begin.succ..r.end) } end end end
Generates a lazy list of a give IO-object using a given block or Proc object to read from this object.
# File lib/lazylist.rb, line 271 def self.io(input, &f) if f input.eof? ? empty : new(delay { f[input] }) { io(input, &f) } else input.eof? ? empty : new(delay { input.readline }) { io(input) } end end
Generates a lazy list which iterates over its previous values computing something like: f(i), f(f(i)), f(f(f(i))), …
# File lib/lazylist.rb, line 265 def self.iterate(i = 0, &f) new(delay { i }) { iterate(f[i], &f) } end
Creates a new LazyList element. The tail can be given either as second argument or as block.
# File lib/lazylist.rb, line 106 def initialize(head = nil, tail = nil, &block) @cached = true @ref_cache = {} if tail if block raise LazyList::Exception, "Use block xor second argument for constructor" end @head, @tail = head, tail elsif block @head, @tail = head, delay(&block) else @head, @tail = nil, nil end end
Generates a finite lazy list beginning with element a and spanning n elements. The data structure members have to support the successor method succ.
# File lib/lazylist.rb, line 241 def self.span(a, n) if n > 0 new(delay { a }) { span(a.succ, n - 1) } else empty end end
Generates a lazy list which tabulates every element beginning with n and succeding with succ by calling the Proc object f or the given block. If none is given the identity function is computed instead.
# File lib/lazylist.rb, line 252 def self.tabulate(n = 0, &f) f = Identity unless f new(delay { f[n] }) { tabulate(n.succ, &f) } end
If n is a Range every element in this range is returned. If n isn’t a Range object the element at index n is returned. If m is given the next m elements beginning the n-th element are returned.
# File lib/lazylist.rb, line 344 def [](n, m = nil) case when Range === n sublist(n) when n < 0 nil when m sublist(n, m) else ref(n).head end end
Append this lazy list to the _*other_ lists, creating a new lists that consists of the elements of this list and the elements of the lists other1, other2, … If any of the lists is infinite, the elements of the following lists will never occur in the result list.
# File lib/lazylist.rb, line 421 def append(*other) if empty? if other.empty? empty else other.first.append(*other[1..-1]) end else self.class.new(delay { head }) { tail.append(*other) } end end
Returns true, if index references into the lazy list are cached for fast access to the referenced elements.
# File lib/lazylist.rb, line 129 def cached? !!@cached end
Returns the cartesian_product of this LazyList and the others as a LazyList of Array tuples. A block can be given to yield to all the created tuples and create a LazyList out of the block results.
# File lib/lazylist.rb, line 585 def cartesian_product(*others) # :yields: tuple case when empty? self when others.empty? block_given? ? map(&Proc.new) : map else product = others[1..-1].inject(product(others[0])) do |intermediate, list| intermediate.product(list) do |existing, new_element| existing + [ new_element ] end end if block_given? block = Proc.new product.map { |tuple| block[*tuple] } else product end end end
Drops the next n elements and returns the rest of this lazy list. n defaults to 1.
# File lib/lazylist.rb, line 467 def drop(n = 1) each(n) { } end
Drops the next n elements, destroys them in the lazy list and returns the rest of this lazy list. Also see each! .
# File lib/lazylist.rb, line 473 def drop!(n = 1) each!(n) { } end
Iterates over all elements. If n is given only n iterations are done. If self is a finite lazy list each returns also if there are no more elements to iterate over.
# File lib/lazylist.rb, line 360 def each(n = nil) s = self if n until n <= 0 or s.empty? yield s.head s = s.tail n -= 1 unless n.nil? end else until s.empty? yield s.head s = s.tail end end s end
Similar to LazyList#each but destroys elements from past iterations perhaps saving some memory. Try to call GC.start from time to time in your block.
# File lib/lazylist.rb, line 379 def each!(n = nil) s = self if n until n <= 0 or s.empty? yield s.head s = s.tail n -= 1 unless n.nil? @head, @tail = s.head, s.tail end else until s.empty? yield s.head s = s.tail @head, @tail = s.head, s.tail end end self end
Returns an empty list.
# File lib/lazylist.rb, line 99 def empty @klass ||= self.class @klass.new(nil, nil) end
Returns true if this is the empty lazy list.
# File lib/lazylist.rb, line 492 def empty? self.peek_head == nil && self.peek_tail == nil end
Returns true, if this lazy list and the other lazy list consist of only equal elements. This is only sensible, if the lazy lists are finite and you can spare the memory.
# File lib/lazylist.rb, line 499 def eql?(other) other.is_a? self.class or return false size == other.size or return false to_a.zip(other.to_a) { |x, y| x == y or return false } true end
Returns one “half” of the product of this LazyList and the other:
list(1,2,3).half_product(list(1,2)).to_a # => [[1, 1], [2, 1], [2, 2], [3, 1], [3, 2]]
block can be used to yield to every pair generated and create a new list element out of it. It defaults to Tuple.
# File lib/lazylist.rb, line 542 def half_product(other, &block) block ||= Tuple if empty? or other.empty? empty else mix( delay { zip(other, &block) }, delay { tail.half_product(other, &block) } ) end end
Returns the head of this list by computing its value.
# File lib/lazylist.rb, line 147 def head @head = force @head end
Inspects the list as far as it has been computed by returning a string of the form [1, 2, 3,… ].
# File lib/lazylist.rb, line 509 def inspect return '[]' if empty? result = '[' first = true s = self seen = {} until s.empty? or Promise === s.peek_head or seen[s.__id__] seen[s.__id__] = true if first first = false else result << ', ' end result << s.head.inspect Promise === s.peek_tail and break s = s.tail end unless empty? if first result << '... ' elsif !s.empty? result << ',... ' end end result << ']' end
Return the last n elements of the lazy list. This is only sensible if the lazy list is finite of course.
# File lib/lazylist.rb, line 479 def last(n = 1) to_a.last n end
Merges this lazy list with the other. It uses the &compare block to decide which elements to place first in the result lazy list. If no compare block is given lambda { |a,b| a < b } is used as a default value.
# File lib/lazylist.rb, line 401 def merge(other, &compare) compare ||= LessThan case when empty? other when other.empty? self when compare[head, other.head] self.class.new(head) { tail.merge(other, &compare) } when compare[other.head, head] self.class.new(other.head) { merge(other.tail, &compare) } else self.class.new(head) { tail.merge(other.tail, &compare) } end end
Returns the (cartesian) product of this LazyList instance and the other. block can be used to yield to every pair generated and create a new list element out of it, but it’s useful to at least return the default Tuple from the block.
# File lib/lazylist.rb, line 563 def product(other, &block) if empty? or other.empty? empty else other_block = if block swap block else block = Tuple SwapTuple end mix( delay { half_product(other, &block)}, delay { other.tail.half_product(self, &other_block) } ) end end
Returns the size. This is only sensible if the lazy list is finite of course.
# File lib/lazylist.rb, line 485 def size inject(0) { |s,| s += 1 } end
Returns the result of sublist_range(n), if n is a Range. The result of sublist_span(n, m), if otherwise.
# File lib/lazylist.rb, line 307 def sublist(n, m = nil) if n.is_a? Range sublist_range(n) else sublist_span(n, m) end end
Returns the sublist, constructed from the Range range indexed elements, of this lazy list.
# File lib/lazylist.rb, line 281 def sublist_range(range) f = range.first l = range.exclude_end? ? range.last - 1 : range.last sublist_span(f, l - f + 1) end
Returns the sublist, that spans m elements starting from the n-th element of this lazy list, if m was given. If m is nonĀpositive, the empty lazy list LazyList::Empty is returned.
If m wasn’t given returns the n long sublist starting from the first (index = 0) element. If n is nonĀpositive, the empty lazy list LazyList::Empty is returned.
# File lib/lazylist.rb, line 294 def sublist_span(n, m = nil) if not m sublist_span(0, n) elsif m > 0 l = ref(n) self.class.new(delay { l.head }) { l.tail.sublist_span(0, m - 1) } else empty end end
Returns the next element by computing its value if necessary.
# File lib/lazylist.rb, line 162 def tail @tail = force @tail end
Takes the next n elements and returns them as an array.
# File lib/lazylist.rb, line 436 def take(n = 1) result = [] each(n) { |x| result << x } result end
Takes the next n elements and returns them as an array. It destroys these elements in this lazy list. Also see each! .
# File lib/lazylist.rb, line 459 def take!(n = 1) result = [] each!(n) { |x| result << x } result end
Takes the range indexes of elements from this lazylist and returns them as an array.
# File lib/lazylist.rb, line 446 def take_range(range) range.map { |i| ref(i).head } end
Returns the head of this list without forcing it.
# File lib/lazylist.rb, line 152 def peek_head @head end
Returns the tail of this list without forcing it.
# File lib/lazylist.rb, line 167 def peek_tail @tail end
Returns the n-th LazyList-Object.
# File lib/lazylist.rb, line 322 def ref(n) if @ref_cache.key?(n) return @ref_cache[n] end s = self i = n while i > 0 do if s.empty? return set_ref(n, self) end s.head # force the head s = s.tail i -= 1 end set_ref(n, s) end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.