Skip to content

Typeless OOP

Blombly aims to support object-oriented programming (OOP) patterns, where structs created by new are essentially objects with attached fields and values. At the same time, OOP is simplified to the level of not having classes/types.

Currying types

The main supposition is that struct "types" are checked implicitly during execution by not creating errors. To assert type compliance, write unit tests that exemplify data accepted by various interfaces. Operations that are expecting base primitives as inputs can cast their inputs or outputs to the desired primitive types. This way, structs serve as monads that can be converted to the base type - or create an error in the process.


The following example consists of a short demonstration of those concepts. In particular it acknowledges that -in the whole program- it would make sense for other.x and other.y to be more complicated structs instead of a float. Ignoring what data they may actually contain, it tries to enforce a conversion into a float. This ensures that the other struct is converted the needed format and moves the burden of the conversion to the latter.

// point.bb
final Point2D = {
    str => "(!{this.x}, !{this.y})";
    add(other) => new {
        Point2D:
        x = this..x + other.x|float;
        y = this..y + other.y|float;
    }
    dot(other) => this.x*other.x|float + this.y*other.y|float;
}
// main.bb
!include "point"

Coords = {
    default name = "coords";
    x = float("!{name}.x="|read);
    y = float("!{name}.y="|read);
}

a = new {Point2D:name="a";Coords:}
b = new {Point2D:name="b";Coords:}
print("a.b = !{a.dot(b)}");

Testing

Blombly offers a simple testing macro that allows you to run a unit or integration test one or more times. There is also an assert statement as a shorthand for checking a condition and failing. Write code so that its inputs can always be randomized by tests. When it comes to random numbers, use a seeded version of distributions to ensure test replicability.

// test.bb
!include "point"

ab_points = {
    rand = random(42); // seeded random generator
    a = new {Point2D:x=next(rand);y=next(rand)}
    b = new {Point2D:x=next(rand);y=next(rand)}
}

final repetitions = 10;
test("dot product", repetitions) {
    ab_points:
    c = a.dot(b);
    assert c>=-2 and c<=2;
}
test("addition", repetitions) {
    ab_points:
    c = a+b;
    assert a.x+b.x == c.x;
    assert a.y+b.y == c.y;
}
> ./blombly test.bb
[  ok  ] dot product 
[  ok  ] addition