rubytree 1.0.0 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,9 +4,9 @@
4
4
  #
5
5
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
6
6
  #
7
- # Time-stamp: <2017-12-21 12:49:25 anupam>
7
+ # Time-stamp: <2021-12-29 13:01:54 anupam>
8
8
  #
9
- # Copyright (C) 2013, 2015, 2017 Anupam Sengupta <anupamsg@gmail.com>
9
+ # Copyright (C) 2013, 2015, 2017, 2021 Anupam Sengupta <anupamsg@gmail.com>
10
10
  #
11
11
  # All rights reserved.
12
12
  #
@@ -36,15 +36,13 @@
36
36
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
37
  #
38
38
 
39
- require_relative '../../../lib/tree'
40
39
  require 'structured_warnings'
41
40
 
42
41
  module Tree::Utils
43
42
  # Provides utility functions to measure various tree metrics.
44
43
  module TreeMetricsHandler
45
44
  # noinspection RubyUnusedLocalVariable
46
- def self.included(base)
47
-
45
+ def self.included(_base)
48
46
  # @!group Metrics and Measures
49
47
 
50
48
  # @!attribute [r] size
@@ -56,7 +54,7 @@ module Tree::Utils
56
54
  #
57
55
  # @return [Integer] Total number of nodes in this (sub)tree.
58
56
  def size
59
- inject(0) {|sum, node| sum + 1 if node}
57
+ inject(0) { |sum, node| sum + 1 if node }
60
58
  end
61
59
 
62
60
  # @!attribute [r] length
@@ -68,7 +66,7 @@ module Tree::Utils
68
66
  # @return [Integer] The total number of nodes in this (sub)tree.
69
67
  # @see #size
70
68
  def length
71
- self.size
69
+ size
72
70
  end
73
71
 
74
72
  # @!attribute [r] node_height
@@ -82,6 +80,7 @@ module Tree::Utils
82
80
  # @return [Integer] Height of the node.
83
81
  def node_height
84
82
  return 0 if is_leaf?
83
+
85
84
  1 + @children.collect { |child| child.node_height }.max
86
85
  end
87
86
 
@@ -100,6 +99,7 @@ module Tree::Utils
100
99
  # @return [Integer] Depth of this node.
101
100
  def node_depth
102
101
  return 0 if is_root?
102
+
103
103
  1 + parent.node_depth
104
104
  end
105
105
 
@@ -134,6 +134,7 @@ module Tree::Utils
134
134
  'Please use node_depth() or node_height() instead (bug # 22535)'
135
135
 
136
136
  return 1 if is_leaf?
137
+
137
138
  1 + @children.collect { |child| child.depth }.max
138
139
  end
139
140
 
@@ -4,9 +4,9 @@
4
4
  #
5
5
  # Author:: Marco Ziccardi and Anupam Sengupta (anupamsg@gmail.com)
6
6
  #
7
- # Time-stamp: <2015-05-30 16:04:00 anupam>
7
+ # Time-stamp: <2021-12-29 13:01:58 anupam>
8
8
  #
9
- # Copyright (C) 2015 Anupam Sengupta <anupamsg@gmail.com>
9
+ # Copyright (C) 2015, 2021 Anupam Sengupta <anupamsg@gmail.com>
10
10
  #
11
11
  # All rights reserved.
12
12
  #
@@ -36,14 +36,11 @@
36
36
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
37
  #
38
38
 
39
- require_relative '../../../lib/tree'
40
-
41
39
  module Tree::Utils
42
40
  # Provides utility methods for path extraction
43
41
  module TreePathHandler
44
42
  # noinspection RubyUnusedLocalVariable
45
- def self.included(base)
46
-
43
+ def self.included(_base)
47
44
  # @!group Node Path
48
45
 
49
46
  # Returns the path of this node from the root as a string, with the node
@@ -90,5 +87,4 @@ module Tree::Utils
90
87
  # @!endgroup
91
88
  end # self.included
92
89
  end
93
-
94
90
  end
@@ -40,7 +40,6 @@ require_relative '../../../lib/tree/utils/utils'
40
40
  # Provides utility methods to merge two {Tree::TreeNode} based trees.
41
41
  # @since 0.9.0
42
42
  module Tree::Utils::TreeMergeHandler
43
-
44
43
  # @!group Merging Trees
45
44
 
46
45
  # Merge two trees that share the same root node and returns <em>a new
@@ -62,7 +61,7 @@ module Tree::Utils::TreeMergeHandler
62
61
  # have the same root node as self.
63
62
  def merge(other_tree)
64
63
  check_merge_prerequisites(other_tree)
65
- merge_trees(self.root.dup, other_tree.root)
64
+ merge_trees(root.dup, other_tree.root)
66
65
  end
67
66
 
68
67
  # Merge in another tree (that shares the same root node) into +this+ tree.
@@ -79,8 +78,8 @@ module Tree::Utils::TreeMergeHandler
79
78
  # @raise [ArgumentError] This exception is raised if _other_tree_ does not
80
79
  # have the same root node as self.
81
80
  def merge!(other_tree)
82
- check_merge_prerequisites( other_tree )
83
- merge_trees( self.root, other_tree.root )
81
+ check_merge_prerequisites(other_tree)
82
+ merge_trees(root, other_tree.root)
84
83
  end
85
84
 
86
85
  private
@@ -97,7 +96,7 @@ module Tree::Utils::TreeMergeHandler
97
96
  'You can only merge in another instance of Tree::TreeNode'
98
97
  end
99
98
 
100
- unless self.root.name == other_tree.root.name
99
+ unless root.name == other_tree.root.name
101
100
  raise ArgumentError,
102
101
  'Unable to merge trees as they do not share the same root'
103
102
  end
@@ -121,10 +120,9 @@ module Tree::Utils::TreeMergeHandler
121
120
  end
122
121
 
123
122
  tree1.children.each do |child|
124
- merge_trees( child, tree2[child.name] ) unless tree2[child.name].nil?
123
+ merge_trees(child, tree2[child.name]) unless tree2[child.name].nil?
125
124
  end
126
125
 
127
126
  tree1
128
127
  end
129
-
130
128
  end
@@ -4,9 +4,9 @@
4
4
  #
5
5
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
6
6
  #
7
- # Time-stamp: <2015-05-30 14:25:57 anupam>
7
+ # Time-stamp: <2021-12-29 13:02:08 anupam>
8
8
  #
9
- # Copyright (C) 2012, 2015 Anupam Sengupta <anupamsg@gmail.com>
9
+ # Copyright (C) 2012, 2015, 2021 Anupam Sengupta <anupamsg@gmail.com>
10
10
  #
11
11
  # All rights reserved.
12
12
  #
@@ -37,8 +37,6 @@
37
37
 
38
38
  # Provides utilities and mixin modules for RubyTree.
39
39
 
40
- require_relative '../../../lib/tree'
41
-
42
40
  module Tree::Utils
43
41
  # Empty module. Being used as a namespace.
44
42
  end
data/lib/tree/version.rb CHANGED
@@ -4,7 +4,7 @@
4
4
  #
5
5
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
6
6
  #
7
- # Copyright (c) 2012, 2013, 2014, 2015, 2017 Anupam Sengupta
7
+ # Copyright (c) 2012, 2013, 2014, 2015, 2017, 2020, 2021 Anupam Sengupta
8
8
  #
9
9
  # All rights reserved.
10
10
  #
@@ -34,8 +34,7 @@
34
34
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
35
  #
36
36
 
37
- #
38
37
  module Tree
39
38
  # Rubytree Package Version
40
- VERSION = '1.0.0'
39
+ VERSION = '1.0.2'.freeze
41
40
  end
data/lib/tree.rb CHANGED
@@ -9,7 +9,7 @@
9
9
  # Author:: Anupam Sengupta (anupamsg@gmail.com)
10
10
  #
11
11
 
12
- # Copyright (c) 2006-2015, 2017 Anupam Sengupta
12
+ # Copyright (c) 2006-2021 Anupam Sengupta
13
13
  #
14
14
  # All rights reserved.
15
15
  #
@@ -47,7 +47,6 @@ require 'tree/tree_deps'
47
47
  # This module also acts as the namespace for all classes in the *RubyTree*
48
48
  # package.
49
49
  module Tree
50
-
51
50
  # == TreeNode Class Description
52
51
  #
53
52
  # This class models the nodes for an *N-ary* tree data structure. The
@@ -109,11 +108,11 @@ module Tree
109
108
  # +content+ attribute for any non-unique node requirements.
110
109
  #
111
110
  # If you want to change the name, you probably want to call +rename+
112
- # instead.
111
+ # instead. Note that +name=+ is a protected method.
113
112
  #
114
113
  # @see content
115
114
  # @see rename
116
- attr_reader :name
115
+ attr_accessor :name
117
116
 
118
117
  # @!attribute [rw] content
119
118
  # Content of this node. Can be +nil+. Note that there is no
@@ -177,7 +176,7 @@ module Tree
177
176
  return nil if is_root?
178
177
 
179
178
  parentage_array = []
180
- prev_parent = self.parent
179
+ prev_parent = parent
181
180
  while prev_parent
182
181
  parentage_array << prev_parent
183
182
  prev_parent = prev_parent.parent
@@ -216,18 +215,20 @@ module Tree
216
215
  #
217
216
  # @see #[]
218
217
  def initialize(name, content = nil)
219
- raise ArgumentError, 'Node name HAS to be provided!' if name == nil
220
- @name, @content = name, content
218
+ raise ArgumentError, 'Node name HAS to be provided!' if name.nil?
219
+
220
+ @name = name
221
+ @content = content
221
222
 
222
- if name.kind_of?(Integer)
223
+ if name.is_a?(Integer)
223
224
  warn StructuredWarnings::StandardWarning,
224
225
  'Using integer as node name.'\
225
226
  ' Semantics of TreeNode[] may not be what you expect!'\
226
227
  " #{name} #{content}"
227
228
  end
228
229
 
229
- self.set_as_root!
230
- @children_hash = Hash.new
230
+ set_as_root!
231
+ @children_hash = {}
231
232
  @children = []
232
233
  end
233
234
 
@@ -254,22 +255,21 @@ module Tree
254
255
  # Alias for {Tree::TreeNode#detached_subtree_copy}
255
256
  #
256
257
  # @see Tree::TreeNode#detached_subtree_copy
257
- alias :dup :detached_subtree_copy
258
+ alias dup detached_subtree_copy
258
259
 
259
260
  # Returns a {marshal-dump}[http://ruby-doc.org/core-1.8.7/Marshal.html]
260
261
  # representation of the (sub)tree rooted at this node.
261
262
  #
262
263
  def marshal_dump
263
- self.collect { |node| node.create_dump_rep }
264
+ collect { |node| node.create_dump_rep }
264
265
  end
265
266
 
266
267
  # Creates a dump representation of this node and returns the same as
267
268
  # a hash.
268
- def create_dump_rep # :nodoc:
269
- {name: @name,
270
- parent: (is_root? ? nil : @parent.name),
271
- content: Marshal.dump(@content)
272
- }
269
+ def create_dump_rep # :nodoc:
270
+ { name: @name,
271
+ parent: (is_root? ? nil : @parent.name),
272
+ content: Marshal.dump(@content) }
273
273
  end
274
274
 
275
275
  protected :create_dump_rep
@@ -284,7 +284,7 @@ module Tree
284
284
  # self and makes itself the root.
285
285
  #
286
286
  def marshal_load(dumped_tree_array)
287
- nodes = { }
287
+ nodes = {}
288
288
  dumped_tree_array.each do |node_hash|
289
289
  name = node_hash[:name]
290
290
  parent_name = node_hash[:parent]
@@ -297,7 +297,7 @@ module Tree
297
297
  # This is the root node, hence initialize self.
298
298
  initialize(name, content)
299
299
 
300
- nodes[name] = self # Add self to the list of nodes
300
+ nodes[name] = self # Add self to the list of nodes
301
301
  end
302
302
  end
303
303
  end
@@ -309,7 +309,7 @@ module Tree
309
309
  #
310
310
  # @return [String] A string representation of the node.
311
311
  def to_s
312
- "Node Name: #{@name} Content: #{(@content.to_s || '<Empty>')} Parent: #{(is_root? ? '<None>' : @parent.name.to_s)} Children: #{@children.length} Total Nodes: #{size}"
312
+ "Node Name: #{@name} Content: #{@content.to_s || '<Empty>'} Parent: #{is_root? ? '<None>' : @parent.name.to_s} Children: #{@children.length} Total Nodes: #{size}"
313
313
  end
314
314
 
315
315
  # @!group Structure Modification
@@ -377,19 +377,18 @@ module Tree
377
377
  # @see #<<
378
378
  def add(child, at_index = -1)
379
379
  # Only handles the immediate child scenario
380
- raise ArgumentError,
381
- 'Attempting to add a nil node' unless child
382
- raise ArgumentError,
383
- 'Attempting add node to itself' if self.equal?(child)
384
- raise ArgumentError,
385
- 'Attempting add root as a child' if child.equal?(root)
386
-
387
- # Lazy mans unique test, won't test if children of child are unique in
380
+ raise ArgumentError, 'Attempting to add a nil node' unless child
381
+
382
+ raise ArgumentError, 'Attempting add node to itself' if equal?(child)
383
+
384
+ raise ArgumentError, 'Attempting add root as a child' if child.equal?(root)
385
+
386
+ # Lazy man's unique test, won't test if children of child are unique in
388
387
  # this tree too.
389
388
  raise "Child #{child.name} already added!"\
390
389
  if @children_hash.include?(child.name)
391
390
 
392
- child.parent.remove! child if child.parent # Detach from the old parent
391
+ child.parent&.remove! child # Detach from the old parent
393
392
 
394
393
  if insertion_range.include?(at_index)
395
394
  @children.insert(at_index, child)
@@ -400,7 +399,7 @@ module Tree
400
399
  "#{insertion_range.min} to #{insertion_range.max} exist."
401
400
  end
402
401
 
403
- @children_hash[child.name] = child
402
+ @children_hash[child.name] = child
404
403
  child.parent = self
405
404
  child
406
405
  end
@@ -408,7 +407,7 @@ module Tree
408
407
  # Return a range of valid insertion positions. Used in the #add method.
409
408
  def insertion_range
410
409
  max = @children.size
411
- min = -(max+1)
410
+ min = -(max + 1)
412
411
  min..max
413
412
  end
414
413
 
@@ -424,7 +423,7 @@ module Tree
424
423
  old_name = @name
425
424
 
426
425
  if is_root?
427
- self.name=(new_name)
426
+ self.name = new_name
428
427
  else
429
428
  @parent.rename_child old_name, new_name
430
429
  end
@@ -441,20 +440,10 @@ module Tree
441
440
  # pass a String (Integer names may cause *surprises*)
442
441
  def rename_child(old_name, new_name)
443
442
  raise ArgumentError, "Invalid child name specified: #{old_name}"\
444
- unless @children_hash.has_key?(old_name)
443
+ unless @children_hash.key?(old_name)
445
444
 
446
445
  @children_hash[new_name] = @children_hash.delete(old_name)
447
- @children_hash[new_name].name=(new_name)
448
- end
449
-
450
- # Protected method to set the name of this node.
451
- # This method should *NOT* be invoked by client code.
452
- #
453
- # @param [Object] new_name The node Name to set.
454
- #
455
- # @return [Object] The new name.
456
- def name=(new_name)
457
- @name = new_name
446
+ @children_hash[new_name].name = new_name
458
447
  end
459
448
 
460
449
  # Replaces the specified child node with another child node on this node.
@@ -510,7 +499,7 @@ module Tree
510
499
  # @param [Tree::TreeNode] parent The parent node.
511
500
  #
512
501
  # @return [Tree::TreeNode] The parent node.
513
- def parent=(parent) # :nodoc:
502
+ def parent=(parent) # :nodoc:
514
503
  @parent = parent
515
504
  @node_depth = nil
516
505
  end
@@ -549,7 +538,7 @@ module Tree
549
538
  # Protected method which sets this node as a root node.
550
539
  #
551
540
  # @return +nil+.
552
- def set_as_root! # :nodoc:
541
+ def set_as_root! # :nodoc:
553
542
  self.parent = nil
554
543
  end
555
544
 
@@ -560,7 +549,7 @@ module Tree
560
549
  # The nodes become immutable after this operation. In effect, the entire tree's
561
550
  # structure and contents become _read-only_ and cannot be changed.
562
551
  def freeze_tree!
563
- each {|node| node.freeze}
552
+ each { |node| node.freeze }
564
553
  end
565
554
 
566
555
  # @!endgroup
@@ -600,14 +589,13 @@ module Tree
600
589
  #
601
590
  # @see #add
602
591
  # @see #initialize
603
- def [](name_or_index, num_as_name=false)
604
- raise ArgumentError,
605
- 'Name_or_index needs to be provided!' if name_or_index == nil
592
+ def [](name_or_index, num_as_name = false)
593
+ raise ArgumentError, 'Name_or_index needs to be provided!' if name_or_index.nil?
606
594
 
607
- if name_or_index.kind_of?(Integer) and not num_as_name
595
+ if name_or_index.is_a?(Integer) && !num_as_name
608
596
  @children[name_or_index]
609
597
  else
610
- if num_as_name and not name_or_index.kind_of?(Integer)
598
+ if num_as_name && !name_or_index.is_a?(Integer)
611
599
  warn StructuredWarnings::StandardWarning,
612
600
  'Redundant use of the `num_as_name` flag for non-integer node name'
613
601
  end
@@ -630,19 +618,18 @@ module Tree
630
618
  # @return [Tree::TreeNode] this node, if a block if given
631
619
  # @return [Enumerator] an enumerator on this tree, if a block is *not* given
632
620
  # noinspection RubyUnusedLocalVariable
633
- def each(&block) # :yields: node
621
+ def each # :yields: node
622
+ return to_enum unless block_given?
634
623
 
635
- return self.to_enum unless block_given?
636
-
637
- node_stack = [self] # Start with this node
624
+ node_stack = [self] # Start with this node
638
625
 
639
626
  until node_stack.empty?
640
- current = node_stack.shift # Pop the top-most node
641
- if current # Might be 'nil' (esp. for binary trees)
642
- yield current # and process it
643
- # Stack children of the current node at top of the stack
644
- node_stack = current.children.concat(node_stack)
645
- end
627
+ current = node_stack.shift # Pop the top-most node
628
+ next unless current # Might be 'nil' (esp. for binary trees)
629
+
630
+ yield current # and process it
631
+ # Stack children of the current node at top of the stack
632
+ node_stack = current.children.concat(node_stack)
646
633
  end
647
634
 
648
635
  self if block_given?
@@ -658,7 +645,7 @@ module Tree
658
645
  #
659
646
  # @return [Tree::TreeNode] this node, if a block if given
660
647
  # @return [Enumerator] an enumerator on this tree, if a block is *not* given
661
- def preordered_each(&block) # :yields: node
648
+ def preordered_each(&block) # :yields: node
662
649
  each(&block)
663
650
  end
664
651
 
@@ -672,8 +659,8 @@ module Tree
672
659
  # @return [Tree::TreeNode] this node, if a block if given
673
660
  # @return [Enumerator] an enumerator on this tree, if a block is *not* given
674
661
  # noinspection RubyUnusedLocalVariable
675
- def postordered_each(&block)
676
- return self.to_enum(:postordered_each) unless block_given?
662
+ def postordered_each
663
+ return to_enum(:postordered_each) unless block_given?
677
664
 
678
665
  # Using a marked node in order to skip adding the children of nodes that
679
666
  # have already been visited. This allows the stack depth to be controlled,
@@ -683,15 +670,15 @@ module Tree
683
670
 
684
671
  until node_stack.empty?
685
672
  peek_node = node_stack[0]
686
- if peek_node.node.has_children? and not peek_node.visited
673
+ if peek_node.node.has_children? && !peek_node.visited
687
674
  peek_node.visited = true
688
675
  # Add the children to the stack. Use the marking structure.
689
676
  marked_children =
690
- peek_node.node.children.map {|node| marked_node.new(node, false)}
677
+ peek_node.node.children.map { |node| marked_node.new(node, false) }
691
678
  node_stack = marked_children.concat(node_stack)
692
679
  next
693
680
  else
694
- yield node_stack.shift.node # Pop and yield the current node
681
+ yield node_stack.shift.node # Pop and yield the current node
695
682
  end
696
683
  end
697
684
 
@@ -711,10 +698,10 @@ module Tree
711
698
  # @return [Tree::TreeNode] this node, if a block if given
712
699
  # @return [Enumerator] an enumerator on this tree, if a block is *not* given
713
700
  # noinspection RubyUnusedLocalVariable
714
- def breadth_each(&block)
715
- return self.to_enum(:breadth_each) unless block_given?
701
+ def breadth_each
702
+ return to_enum(:breadth_each) unless block_given?
716
703
 
717
- node_queue = [self] # Create a queue with self as the initial entry
704
+ node_queue = [self] # Create a queue with self as the initial entry
718
705
 
719
706
  # Use a queue to do breadth traversal
720
707
  until node_queue.empty?
@@ -739,9 +726,9 @@ module Tree
739
726
  #
740
727
  # @return [Array<Tree::TreeNode>] An array of the child nodes, if no block
741
728
  # is given.
742
- def children
729
+ def children(&block)
743
730
  if block_given?
744
- @children.each {|child| yield child}
731
+ @children.each(&block)
745
732
  self
746
733
  else
747
734
  @children.clone
@@ -763,15 +750,37 @@ module Tree
763
750
  # @return [Tree::TreeNode] this node, if a block if given
764
751
  # @return [Array<Tree::TreeNode>] An array of the leaf nodes
765
752
  # noinspection RubyUnusedLocalVariable
766
- def each_leaf(&block)
753
+ def each_leaf
767
754
  if block_given?
768
- self.each { |node| yield(node) if node.is_leaf? }
755
+ each { |node| yield(node) if node.is_leaf? }
769
756
  self
770
757
  else
771
758
  self.select { |node| node.is_leaf? }
772
759
  end
773
760
  end
774
761
 
762
+ # Yields every level of the (sub)tree rooted at this node to the
763
+ # specified block.
764
+ #
765
+ # Will yield this node as well since it is considered the first level.
766
+ #
767
+ # @yieldparam level [Array<Tree::TreeNode>] All nodes in the level
768
+ #
769
+ # @return [Tree::TreeNode] this node, if a block if given
770
+ # @return [Enumerator] an enumerator on this tree, if a block is *not* given
771
+ def each_level
772
+ if block_given?
773
+ level = [self]
774
+ until level.empty?
775
+ yield level
776
+ level = level.map(&:children).flatten
777
+ end
778
+ self
779
+ else
780
+ each
781
+ end
782
+ end
783
+
775
784
  # @!endgroup
776
785
 
777
786
  # @!group Navigating the Child Nodes
@@ -866,9 +875,11 @@ module Tree
866
875
  self
867
876
  else
868
877
  return [] if is_root?
878
+
869
879
  siblings = []
870
- parent.children {|my_sibling|
871
- siblings << my_sibling if my_sibling != self}
880
+ parent.children do |my_sibling|
881
+ siblings << my_sibling if my_sibling != self
882
+ end
872
883
  siblings
873
884
  end
874
885
  end
@@ -930,8 +941,9 @@ module Tree
930
941
  # this node is a 'predecessor'. Returns 'nil' if the other
931
942
  # object is not a 'Tree::TreeNode'.
932
943
  def <=>(other)
933
- return nil if other == nil || other.class != Tree::TreeNode
934
- self.name <=> other.name
944
+ return nil if other.nil? || other.class != Tree::TreeNode
945
+
946
+ name <=> other.name
935
947
  end
936
948
 
937
949
  # Pretty prints the (sub)tree rooted at this node.
@@ -940,9 +952,10 @@ module Tree
940
952
  # @param [Integer] max_depth optional maximum depth at which the printing
941
953
  # with stop.
942
954
  # @param [Proc] block optional block to use for rendering
943
- def print_tree(level = self.node_depth, max_depth = nil,
955
+ def print_tree(level = node_depth, max_depth = nil,
944
956
  block = lambda { |node, prefix|
945
- puts "#{prefix} #{node.name}" })
957
+ puts "#{prefix} #{node.name}"
958
+ })
946
959
  prefix = ''
947
960
 
948
961
  if is_root?
@@ -960,10 +973,11 @@ module Tree
960
973
  # Exit if the max level is defined, and reached.
961
974
  return unless max_depth.nil? || level < max_depth
962
975
 
963
- children { |child|
964
- child.print_tree(level + 1,
965
- max_depth, block) if child } # Child might be 'nil'
976
+ # Child might be 'nil'
977
+ children do |child|
978
+ child&.print_tree(level + 1,
979
+ max_depth, block)
980
+ end
966
981
  end
967
-
968
982
  end
969
983
  end