lib/sycamore/tree.rb in sycamore-0.3.0 vs lib/sycamore/tree.rb in sycamore-0.3.1
- old
+ new
@@ -63,13 +63,20 @@
##
# Creates a new empty Tree.
#
def initialize
- @data = Hash.new
end
+ protected def data
+ @data ||= Hash.new
+ end
+
+ protected def clear_data
+ @data = nil
+ end
+
##
# Creates a new Tree and initializes it with the given data.
#
# @param (see #add)
# @return [Tree]
@@ -216,42 +223,42 @@
end
alias << add
protected def add_node(node)
- @data[node] ||= Nothing
+ data[node] ||= Nothing
self
end
##
# @api private
#
def clear_child_of_node(node)
- @data[valid_node! node] = Nothing
+ data[valid_node! node] = Nothing
self
end
##
# @api private
#
def add_node_with_empty_child(node)
valid_node! node
- if @data.fetch(node, Nothing).nothing?
- @data[node] = new_child(node)
+ if data.fetch(node, Nothing).nothing?
+ data[node] = new_child(node)
end
self
end
private def add_child(node, children)
return add_node(node) if Nothing.like?(children)
add_node_with_empty_child(node)
- @data[node] << children
+ data[node] << children
self
end
private def add_tree(tree)
@@ -327,11 +334,11 @@
end
alias >> delete
protected def delete_node(node)
- @data.delete(node)
+ data.delete(node)
self
end
protected def delete_tree(tree)
@@ -489,11 +496,11 @@
# tree.size # => 3
# tree.clear
# tree.size # => 0
#
def clear
- @data.clear
+ data.clear
self
end
##
@@ -507,11 +514,11 @@
# tree.to_h # => {foo: {bar: []}}
# tree.compact
# tree.to_h # => {foo: :bar}
#
def compact
- @data.each do |node, child| case
+ data.each do |node, child| case
when child.nothing? then next
when child.empty? then clear_child_of_node(node)
else child.compact
end
end
@@ -533,11 +540,11 @@
# tree = Tree[foo: [:bar, :baz]]
# tree.nodes # => [:foo]
# tree[:foo].nodes # => [:bar, :baz]
#
def nodes
- @data.keys
+ data.keys
end
alias keys nodes # Hash compatibility
@@ -603,11 +610,11 @@
# @todo Should we differentiate the case of a leaf and a not present node? How?
#
def child_of(node)
valid_node! node
- Nothing.like?(child = @data[node]) ? Absence.at(self, node) : child
+ Nothing.like?(child = data[node]) ? Absence.at(self, node) : child
end
##
# The child tree of a node at a path.
#
@@ -682,11 +689,11 @@
#
def fetch(node, *default, &block)
return fetch_path(node, *default, &block) if node.is_a? Path
valid_node! node
- child = @data.fetch(node, *default, &block)
+ child = data.fetch(node, *default, &block)
if child.equal? Nothing
child = case
when block_given? then yield
when !default.empty? then default.first
else raise ChildError, "node #{node.inspect} has no child tree"
@@ -752,11 +759,11 @@
# > b
#
def each_node(&block)
return enum_for(__callee__) unless block_given?
- @data.each_key(&block)
+ data.each_key(&block)
self
end
alias each_key each_node # Hash compatibility
@@ -781,11 +788,11 @@
# > b => #<Tree: Nothing>
#
def each_pair(&block)
return enum_for(__callee__) unless block_given?
- @data.each_pair(&block)
+ data.each_pair(&block)
self
end
alias each each_pair
@@ -868,11 +875,11 @@
# Tree[1 => 2].include_node? Sycamore::Path[1,2] # => true
#
def include_node?(node)
return include_path?(node) if node.is_a? Path
- @data.include?(node)
+ data.include?(node)
end
alias member? include_node? # Hash compatibility
alias has_key? include_node? # Hash compatibility
alias key? include_node? # Hash compatibility
@@ -952,11 +959,11 @@
# tree.delete("a")
# tree.size # => 3
# tree["e"].size # => 2
#
def size
- @data.size
+ data.size
end
##
# The number of {#nodes nodes} in this tree and all of their children.
#
@@ -969,11 +976,11 @@
# tree.total_size # => 7
# tree["e"].total_size # => 2
#
def total_size
total = size
- @data.each { |_, child| total += child.total_size }
+ data.each { |_, child| total += child.total_size }
total
end
alias tsize total_size
@@ -999,11 +1006,11 @@
# @example
# Tree.new.empty? # => true
# Tree[a: 1].empty? # => false
#
def empty?
- @data.empty?
+ data.empty?
end
alias blank? empty?
##
@@ -1144,11 +1151,11 @@
# A hash code of this tree.
#
# @return [Fixnum]
#
def hash
- @data.hash ^ self.class.hash
+ data.hash ^ self.class.hash
end
##
# Checks if this tree has the same content as another tree.
#
@@ -1163,11 +1170,11 @@
# tree1.eql? tree2 # => false
# tree1.eql? tree3 # => true
# tree1.eql? tree4 # => false
#
def eql?(other)
- (other.instance_of?(self.class) and @data.eql?(other.data)) or
+ (other.instance_of?(self.class) and data.eql?(other.data)) or
(other.instance_of?(Absence) and other.eql?(self))
end
##
# Checks if this tree has the same content as another tree, but ignores empty child trees.
@@ -1337,11 +1344,11 @@
return {} if empty?
# not the nicest, but fastest way to inject on hashes, as noted here:
# http://stackoverflow.com/questions/3230863/ruby-rails-inject-on-hashes-good-style
hash = {}
- @data.each do |node, child|
+ data.each do |node, child|
hash[node] = child.to_native_object(*args)
end
hash
end
@@ -1442,20 +1449,20 @@
##
# Clones the whole tree.
#
def initialize_clone(other)
super
- @data = Hash.new
+ clear_data
add other
end
##
# Deep freezes the whole tree.
#
# @see http://ruby-doc.org/core/Object.html#method-i-freeze
#
def freeze
- @data.freeze
+ data.freeze
each { |_, child| child.freeze }
super
end
end # Tree