class PropCheck::LazyTree

A Rose tree with the root being eager, and the children computed lazily, on demand.

Attributes

root[RW]

Public Class Methods

new(root, children = [].lazy) click to toggle source
# File lib/prop_check/lazy_tree.rb, line 13
def initialize(root, children = [].lazy)
  @root = root
  @children = children
end
wrap(val) click to toggle source
LazyTree.new(root_root, combined_children)

end

# File lib/prop_check/lazy_tree.rb, line 50
def self.wrap(val)
  LazyTree.new(val)
end
zip(trees) click to toggle source

TODO: fix implementation

# File lib/prop_check/lazy_tree.rb, line 102
def self.zip(trees)
  # p "TREES: "
  # p trees.to_a
  # p "END TREES"
  # raise "Boom!" unless trees.to_a.is_a?(Array) && trees.to_a.first.is_a?(LazyTree)
  # p self
  new_root = trees.to_a.map(&:root)
  # p new_root
  # new_children = trees.permutations.flat_map(&:children)
  new_children = permutations(trees).map { |children| LazyTree.zip(children) }
  # p new_children
  LazyTree.new(new_root, new_children)
end

Private Class Methods

permutations(trees) click to toggle source
# File lib/prop_check/lazy_tree.rb, line 116
                     def self.permutations(trees)
  # p trees
  trees.lazy.each_with_index.flat_map do |tree, index|
    tree.children.map do |child|
      child_trees = trees.to_a.clone
      child_trees[index] = child
      # p "CHILD TREES:"
      # p child_trees
      child_trees.lazy
    end
  end
end

Public Instance Methods

bind(&fun) click to toggle source
# File lib/prop_check/lazy_tree.rb, line 54
def bind(&fun)
  inner_tree = fun.call(root)
  inner_root = inner_tree.root
  inner_children = inner_tree.children
  mapped_children = children.map { |child| child.bind(&fun) }

  combined_children = PropCheck::Helper.lazy_append(inner_children, mapped_children)

  LazyTree.new(inner_root, combined_children)
end
children() click to toggle source
# File lib/prop_check/lazy_tree.rb, line 18
def children
  @children.reject { |child| child.root == :"_PropCheck.filter_me" }
end
each(&block) click to toggle source

Turns a LazyTree in a long lazy enumerable, with the root first followed by its children (and the first children's result before later children; i.e. a depth-first traversal.)

Be aware that this lazy enumerable is potentially infinite, possibly uncountably so.

>> LazyTree.new(1, [LazyTree.new(2, [LazyTree.new(3)]), LazyTree.new(4)]).each.force
=> [1, 4, 2, 3]
# File lib/prop_check/lazy_tree.rb, line 74
def each(&block)
  self.to_enum(:each) unless block_given?

  squish([])
  .each(&block)
end
map(&block) click to toggle source

Maps `block` eagerly over `root` and lazily over `children`, returning a new LazyTree as result.

>> LazyTree.new(1, [LazyTree.new(2, [LazyTree.new(3)]), LazyTree.new(4)]).map(&:next).to_a
=> LazyTree.new(2, [LazyTree.new(3, [LazyTree.new(4)]), LazyTree.new(5)]).to_a
# File lib/prop_check/lazy_tree.rb, line 27
def map(&block)
  new_root = block.call(root)
  new_children = children.map { |child_tree| child_tree.map(&block) }
  LazyTree.new(new_root, new_children)
end
to_a() click to toggle source

Fully evaluate the LazyTree into an eager array, with the root first followed by its children (and the first children's result before later children; i.e. a depth-first traversal.)

Be aware that calling this might make Ruby attempt to evaluate an infinite collection. Therefore, it is mostly useful for debugging; in production you probably want to use the other mechanisms this class provides..

>> LazyTree.new(1, [LazyTree.new(2, [LazyTree.new(3)]), LazyTree.new(4)]).to_a
=> [1, 4, 2, 3]
# File lib/prop_check/lazy_tree.rb, line 96
def to_a
  each
    .force
end

Protected Instance Methods

squish(arr) click to toggle source
# File lib/prop_check/lazy_tree.rb, line 81
          def squish(arr)
  new_children = self.children.reduce(arr) { |acc, elem| elem.squish(acc) }
  PropCheck::Helper.lazy_append([self.root], new_children)
end