It’s been due time to add control flow into Compost. We have it now!

Match Expressions

Match expressions allow you to use different flows based on some element’s type. Here’s an example:

lets
    StringOrNothing(thing: @String | ?): String
        match matchedThing: thing
            @String: matchedThing.String
            ?      : 'Nothing'

It takes a thing that implements the String trait or not. If it implements String, it returns that string. Otherwise it returns the String ’nothing'.

Booleans and If Expressions

We now have hte boolean literals true and false. There are also the operators =, < and >, implemented on Int, that can return a boolean. = is also implemented on String, and can be implemented on any module using Op\Eq. Booleans themselves have the boolean operators !, & and |.

Booleans come in useful with the new if then else expressions, which need a condition resulting in a boolean type. The else part is necessary, because every expression needs to return something.

Example:

lets
    PrintInOrder(a: @String & Op\Gt, b: @String & Op\Gt): String
        if a > b
        then b.String + ', ' + a.String
        else a.String + ', ' + b.String

    Main: String
        PrintInOrder(a: 2, b: 1)

Linked List

Using these new toys, let’s see what we can build. First off, a linked list of numbers!

mod LinkedList
    class
         prev: Self | ?
         item: Int
    traits
         First: Int
         Last: Int
         Sum: Int
         Len: Int
         Push: (pushed: Int) -> Self
    defs
        Last: item
        First
            match prev: prev
                Self: prev.First
                ?   : item
        Len
            match prev: prev
                Self: prev.Len + 1
                ?   : 1
        Sum
            match prev: prev
                Self: prev.Sum + item
                ?   : item
        Push
            LinkedList
                prev: Self
                item: pushed
        String
            match prev: prev
                Self: prev.String + ', ' + item.String
                ?   : item.String
 
lets
    MyList: LinkedList
        LinkedList
            prev: ?
            item: 1
        .Push(pushed: 2)
        .Push(pushed: 3)
        .Push(pushed: 4)

    Main: String
        MyList.String

I store the list in reverse order to make pushing easier.

Binary Tree

We can also make a binary tree structure that automatically sorts inserted numbers.

mod BinaryTreeItem
    using
        Op\Lt
        Op\Gt
        Op\Eq
        String

mod BinaryTree
    class
        item: BinaryTreeItem
        leftNode: Self | ?
        rightNode: Self | ?
    traits
        Insert: (insertedItem: BinaryTreeItem) -> Self
        Contains: (givenItem: BinaryTreeItem) -> Bool
        Max: BinaryTreeItem
        Min: BinaryTreeItem
        Size: Int
    defs
        Insert
            if insertedItem < item
            then
                match node: leftNode
                    Self
                        BinaryTree
                            item: item
                            leftNode: node.Insert(insertedItem: insertedItem)
                            rightNode: rightNode
                    ?
                        BinaryTree
                            item: item
                            leftNode: BinaryTree
                                item: insertedItem
                                leftNode: ?
                                rightNode: ?
                            rightNode: rightNode
            else if insertedItem > item
            then
                match node: rightNode
                    Self
                        BinaryTree
                            item: item
                            leftNode: leftNode
                            rightNode: node.Insert(insertedItem: insertedItem)
                    ?
                        BinaryTree
                            item: item
                            leftNode: leftNode
                            rightNode: BinaryTree
                                item: insertedItem
                                leftNode: ?
                                rightNode: ?
            else Self
        Contains
            item = (givenItem)
            | match node: leftNode
                Self: node.Contains(givenItem: givenItem)
                ?:    false
            | match node: rightNode
                Self: node.Contains(givenItem: givenItem)
                ?:    false
        Max
            match node: rightNode
                Self: node.Max
                ?:    item
        Min
            match node: leftNode
                Self: node.Min
                ?:    item
        Size
            match node: leftNode
                Self: node.Size
                ?:    Int(value: 0)
            + match node: rightNode
                Self: node.Size
                ?:    Int(value: 0)
            + 1

What’s to come

To make these data structures more usable, I will be working a templates feature. I’m also working on an Iterator module with mapping, filtering, reducing and collecting functionality, which will also use type templating. That will make Compost a lot more useful!