Recursive Types

Claro supports the definition of new types that contain recursive self-references. For example a binary tree structure is a classic recursive data structure where each Node in the tree contains a left and right child that may either be another Node or nothing. The below is the definition of a Node that can only hold ints:

Fig 1:


newtype IntNode : struct {
  val: int,
  left: oneof<IntNode, std::Nothing>,
  right: oneof<IntNode, std::Nothing>
}

For example, the following initializes a simple tree with the root pointing to two children that have no children of their own:

Fig 2:


var tree =
  IntNode({
    val = 1,
    left = IntNode({val = 2, left = std::Nothing, right = std::Nothing}),
    right = IntNode({val = 3, left = std::Nothing, right = std::Nothing})
  });
print(tree);

Output:

IntNode({val = 1, left = IntNode({val = 2, left = Nothing, right = Nothing}), right = IntNode({val = 3, left = Nothing, right = Nothing})})

Parameterized Recursive Types

Of course, the above IntNode definition is too constrained, so ideally we'd define a single Node type that's able to represent trees of arbitrary data types. So, a better Node type definition looks like:

Fig 3:


newtype Node<T> : struct {
  val: T,
  left: oneof<Node<T>, std::Nothing>,
  right: oneof<Node<T>, std::Nothing>
}

Initialization looks exactly the same as in the concrete IntNode example above:

Fig 4:


var tree =
  Node({
    val = 1,
    left = Node({val = 2, left = std::Nothing, right = std::Nothing}),
    right = Node({val = 3, left = std::Nothing, right = std::Nothing})
  });
print(tree);

Output:

Node({val = 1, left = Node({val = 2, left = Nothing, right = Nothing}), right = Node({val = 3, left = Nothing, right = Nothing})})