Many definitions, classes, and enums are only useful on a specific set of data. Occasionally, an algorithm or data type is useful for any kind of data type.

A simple generic function can be written as follows:

define interpolate[A](value: A): String
{
    return value ++ ""
}

print(interpolate(1))         # 1
print(interpolate([1, 2, 3])) # [1, 2, 3]
print(interpolate)            # <function interpolate>

Generics start at A and work up to Z. It is currently not possible to have custom names for generics. A more complex generic function can be written as follows.

define transform[A, B](value: A, fn: Function(A => B)): B
{
    return fn(value)
}

print(transform([1, 2, 3], List.size)) # 3

Classes are also able to make use of generics. Generics in class methods start after class generics.

class Container[A]
{
    public var @values: List[A] = []

    public define send(v: A): self
    {
        @values.push(v)
    }

    public define apply[B](f: Function(A => B)): List[B]
    {
        var result: List[B] = []

        for i in 0...@values.size() - 1: {
            @values[i]
                |> f
                |> result.push
        }

        return result
    }
}

var v = Container()
            .@(Container[String])
            .send("1")
            .send("100")
            .send("1b")
            .send("5000")
            .send("a")
            .apply(String.parse_i)
            .select(Option.is_some)
            .map(Option.unwrap)
            .fold(0, (|a, b| a + b ))

print(v) # 5101

Enums and their variants also support generics.

enum Tree[A]
{
    Branch(Tree[A]...),
    Leaf(A)

    define all: List[A]
    {
        var result_list: List[A] = []
        var source_list: List[Tree[A]] = [self]

        while source_list.size(): {
            var s = source_list.pop()

            match s: {
                case Leaf(result):
                    result_list.push(result)
                case Branch(target_list):
                    source_list = source_list.merge(target_list)
            }
        }

        return result_list
    }
}

var v =
    Branch(
        Branch(
            Leaf(1),
            Leaf(20)
        ),
        Leaf(300),
        Branch(
            Leaf(4000),
            Leaf(50000)
        )
    )
    .all()
    .fold(0, (|a, b| a + b ))

print(v) # 54321