Users › 07 Generics and operators

Generics and operators

Use generic native libraries, and overload operators on your own classes.

1. Generics live in native libraries

Lopolith classes cannot declare type parameters. Generic types are declared by native plugins through slots (<?a, ?b>) and used from the language with concrete types:

%native com.example.Set<?a>
    void put(?a value)
    int size()
    ?a get(int index)
Set<int> s = new Set<int>()
s.put(42)
int v = s.get(0)

Set<String> names = new Set<String>()
Set<Set<int>> nested = new Set<Set<int>>()

The standard library currently ships no generic class, so the syntax above is the contract rather than a runnable example. To provide one, write a native plugin — the native track shows how slots appear in the .so metadata.

2. Variadic native methods

A native method may end with ... to accept any number of arguments of any type (no implicit conversions). Std.print is the example you have already used; the limit is 64 arguments.

3. Operators are methods

OperatorMethod
+ - * / %___add ___subtract ___multiply ___divide ___modulo
== / !=___equals (!= negates it)
< > <= >=___compareTo
& | ^ ~ << >>___bitAnd ___bitOr ___bitXor ___bitNot ___shiftLeft ___shiftRight
%class com.example.Vector
    pub int x
    pub int y

    void ___init(int x, int y) {
        this.x = x
        this.y = y
    }

    Vector ___add(Vector o) {
        return new Vector(this.x + o.x, this.y + o.y)
    }

    Vector ___add(int s) {              // overloads are allowed
        return new Vector(this.x + s, this.y + s)
    }

    bool ___equals(Vector o) {
        return this.x == o.x && this.y == o.y
    }

4. Equality

OperatorMeaning
==Value equality: primitives compare directly; classes go through ___equals; arrays are a compile error.
!=Negation of ==.
=== / !==Reference identity (address). Primitives are a compile error; arrays are a compile error.

5. Ternary

int x = 5 > 3 ? 100 : 200
int r = a ? b : c ? d : e          // right-associative

The condition must be bool. The two branches must share a common type: numeric promotion, the same class, the same array type, a shared interface (both classes implement it), or a shared interface token. Only the selected branch is evaluated.

6. Try it

%simple com.example.ops.Demo implements Main
    #import Std
    int run(int argc, String[] argv) Main@run {
        $Vec a = new $Vec(1, 2)
        $Vec b = new $Vec(3, 4)
        $Vec c = a + b
        $Vec d = a + 10
        bool same = c == new $Vec(4, 6)
        Std.print("c=", c.x, ",", c.y, " d=", d.x, ",", d.y, " same=", same, "\n")
        return 0
    }

%sub Vec
    int x
    int y

    void ___init(int x, int y) {
        this.x = x
        this.y = y
    }

    $Vec ___add($Vec o) {
        return new $Vec(this.x + o.x, this.y + o.y)
    }

    $Vec ___add(int s) {
        return new $Vec(this.x + s, this.y + s)
    }

    bool ___equals($Vec o) {
        return this.x == o.x && this.y == o.y
    }
c=4,6 d=11,12 same=true