     '\n' + idt + @constructor.name + (child.toString(idt + TAB) for child in @children()).join('')
 
   children: ->
-    _children: []
-    @_each_child (child) -> _children.push(child)
-    _children
-
-  _each_child: (func) ->
-    for attr in @_children_attributes
-      child_collection: this[attr]
-      continue unless child_collection?
-      if child_collection instanceof Array
-        i: 0
-        for child in child_collection
-          result: func(child, attr, i)
-          return if result is false
-          i += 1
-      else
-        func(child_collection, attr)
-
-  _traverse_children: (cross_scope, func) ->
-    return unless @_children_attributes
-    @_each_child (child, attr, i) ->
+    nodes: []
+    @each_child (node) -> nodes.push node
+    nodes
+
+  each_child: (func) ->
+    for attr in @children_attributes when this[attr]
+      for child in flatten [this[attr]]
+        return if func(child) is false
+
+  traverse_children: (cross_scope, func) ->
+    return unless @children_attributes
+    @each_child (child) ->
       func.apply(this, arguments)
-      child._traverse_children(cross_scope, func) if child instanceof BaseNode
+      child.traverse_children(cross_scope, func) if child instanceof BaseNode
 
   # Default implementations of the common node identification methods. Nodes
   # will override these with custom logic, if needed.

    @is_pure_statement() or @contains (n) -> n.is_pure_statement()

  # Perform an in-order traversal of the AST. Crosses scope boundaries.
  traverse: (block) -> @_traverse_children true, block

  # `toString` representation of the node, for inspecting the parse tree.
  # This is what `coffee --nodes` prints out.

  # scope boundaries.
  contains: (block) ->
    contains: false
    @traverse_children false, (node) ->
      if block(node)
        contains: true
        return false
    contains

  # Is this node of a certain type, or does it contain the type?
  contains_type: (type) ->
