Skip to content
FutureBlitz

    Install

    Guide

    Generics and Interfaces

    Interfaces with defaults, the built-in ones, generic Functions and types, constraints, and Where.

    An Interface names Methods, Properties, and Operators a type promises, and can give Methods a default. A generic Function or type takes type parameters, and constraints, which are Interfaces, say what it can do with them. Each use of a generic is compiled for its types, so generic code is as fast as code written for one type.

    Interfaces

    A Class implements an Interface by listing it and having its members. A value of the Interface’s type is an object of any Class that implements it.

    Import std.core
    
    Interface Damageable
        Method Hurt(amount: Int)
        ReadOnly Property Health: Int
    
        Method Kill()
            Hurt(Health)
        End Method
    End Interface
    
    Class Crate Implements Damageable
        Field hp: Int = 10
        Method Hurt(amount: Int)
            hp -= amount
        End Method
        Property Health: Int
            Get => hp
        End Property
    End Class
    
    Class Goblin Implements Damageable
        Field hp: Int = 25
        Method Hurt(amount: Int)
            hp -= amount / 2
        End Method
        Property Health: Int
            Get => hp
        End Property
    End Class
    
    Local things: Damageable[] = [Crate(), Goblin()]
    For t In things
        t.Hurt(8)
        Print(t.Health)
    End For
    things[1].Kill()
    Print(things[1].Health)
    Output
    2
    21
    11

    The built-in Interfaces

    std.core’s Interfaces are what the language’s own operators and features go through:

    InterfaceWhat it gives
    Equatable== and !=
    Comparable<, >, <=, >=, and sorting
    Hashablea Hash(), for Map keys and Set elements
    Printablea ToString(), for strings and Print
    Numeric+, -, *, /, Zero(), and One()
    Import std.core
    Import std.collections
    
    Struct Version Implements Comparable, Printable
        Field major: Int
        Field minor: Int
    
        Operator ==(a: Version, b: Version): Bool => a.major == b.major && a.minor == b.minor
        Operator <(a: Version, b: Version): Bool => a.major < b.major || (a.major == b.major && a.minor < b.minor)
        Method ToString(): String => "{major}.{minor}"
    End Struct
    
    Local versions = [Version(1, 10), Version(0, 9), Version(1, 2)]
    versions.Sort()
    Print(versions)
    Print(Version(1, 2) > Version(0, 9))
    Output
    [0.9, 1.2, 1.10]
    True

    Generic Functions and types

    Import std.core
    
    Function Sum<T: Numeric>(values: T[]): T
        Local total = T.Zero()
        For v In values
            total += v
        End For
        Return total
    End Function
    
    Class Stack<T>
        Field items: T[] = []
    
        Method Push(item: T)
            items.Add(item)
        End Method
    
        Method Pop(): T?
            If items.Count == 0 Then Return Null
            Local top = items[items.Count - 1]
            items.RemoveAt(items.Count - 1)
            Return top
        End Method
    End Class
    
    Print(Sum([1, 2, 3]), Sum([0.5, 0.25]))
    
    Local undo = Stack<String>()
    undo.Push("draw line")
    undo.Push("fill")
    Print(undo.Pop() ?? "", undo.Pop() ?? "", undo.Pop() ?? "nothing")
    Output
    6 0.75
    fill draw line nothing

    Type arguments are inferred from a call’s arguments where they can be, and written where they can’t, as Stack<String>().

    Where

    A constraint goes inline, <T: Hashable>, when it’s one on one type parameter. More, or one that relates two, go on Where lines; a Where on a Method makes it there only for the types that meet it.

    Import std.core
    
    Class Bag<T>
        Field items: T[] = []
    
        Method Add(item: T)
            items.Add(item)
        End Method
    
        Method Total(): T
            Where T: Numeric
            Local total = T.Zero()
            For item In items
                total += item
            End For
            Return total
        End Method
    End Class
    
    Local coins = Bag<Int>()
    coins.Add(5)
    coins.Add(20)
    Print(coins.Total())
    
    Local names = Bag<String>()
    names.Add("Ada")
    Print(names.items)
    Output
    25
    [Ada]

    names.Total() wouldn’t compile, since a String isn’t Numeric.

    Report an issue with this page or with FutureBlitz on GitHub.