The Cobra Programming Language
How To
PrintHelloWorld
WriteBasicSyntax
UseProperties
MakeAnIfElseLadder
MakeABranchStatement
DeclareInits
MakeAClassHierarchy
UseNilAndNilableTypes
UseDynamicTyping
DeclareVariableNumberOfArgs
ReadAndWriteFiles
CheckInheritanceAndImplementation
ImplementIEnumerable1
ImplementIEnumerable2
IterateThroughRecursiveDataWithYield
MakeACollectionClass
AccessMySQL
"""
Interate Through Recursize Data With Yield

If you study the _scanInOrder method below you will see that implementing it with `yield` is very
straightforward. Without `yield` the alternative is to write a helper class that implements
IEnumerator<of T> and maintains state variables to track its current position in between calls to
.moveNext. Yuck!

This example was adapted from http://msdn.microsoft.com/msdnmag/issues/06/00/C20/default.aspx
"""


class Node<of T>
    where T must be IComparable<of T>

    var _left as Node<of T>?
    var _right as Node<of T>?
    var _item as T

    def init(item as T)
        .init(item, nil, nil)

    def init(item as T, left as Node<of T>?, right as Node<of T>?)
        _item = item
        _left = left
        _right = right

    pro left from var

    pro right from var

    get item from var

    def compareTo(node as Node<of T>) as int
        # this method enables comparison operators in Cobra like "a < b" where a and b are Nodes
        return .item.compareTo(node.item)

    def toString as String is override
        return '[.getType.name](item=[.item])'

    def dump
        print this stop
        if _left
            print ' left:', _left stop
        if _right
            print ' right:', _right stop
        print
        if _left
            _left.dump
        if _right
            _right.dump


class BinaryTree<of T>
    where T must be IComparable<of T>

    var _root as Node<of T>
    
    def init(root as Node<of T>)
        _root = root

    pro root from var
    
    def add(items as vari T)
        for item in items
            .add(item)
    
    def add(item as T)
        _add(Node<of T>(item), _root)
    
    def _add(newNode as Node<of T>, root as Node<of T>)
        if newNode > root
            right = root.right
            if right
                _add(newNode, right)
            else
                root.right = newNode
        else if newNode < root
            left = root.left
            if left
                _add(newNode, left)
            else
                root.left = newNode

    get inOrder as IEnumerable<of T>
        return _scanInOrder(_root, 0)

    def _scanInOrder(node as Node<of T>?, level) as IEnumerable<of T>
        if node
            if node.left
                for item in _scanInOrder(node.left to !, level+1)
                    yield item
            yield node.item
            if node.right
                for item in _scanInOrder(node.right to !, level+1)
                    yield item


class Program

    def main is shared
        tree = BinaryTree<of int>(Node<of int>(0))
        tree.add(4, 6, 2, 7, 5, 3, 1)
        values = List<of int>()
        for value in tree.inOrder
            # print value
            values.add(value)
        assert values == [0, 1, 2, 3, 4, 5, 6, 7]