A fast, statically-typed interpreted language that combines Rust-like syntax with Python's ease-of-use.



Try it in your browser GitHub
Very, very fast
~10x faster than Python, competitive with LuaJIT (-joff).
See the benchmarks.

Familiar syntax
As easy as Python, while borrowing from other low-level languages
Statically typed
Zero annotations, full type inference & polymorphism.
FFI support
Call C/dynamic libraries directly from Keel with a native/easy syntax.
Embeddable
Keel can be embedded in other programs through a C ABI.



Examples

struct Point { x: int, y: int }

fn add(a, b) {
    return a + b;
}

fn main() {
    let p = Point { x: 3, y: 4 };
    print(add(p.x, p.y)); // 7
    print(add("Hello, ", "world!")); // Hello, world!

    let nums = [4, 2, 6, 1, 7];
    if nums[0] == 4 {
        nums.sort();
        print(if nums[0] == 1 { nums[0..3] } else { -1 }); // [1,2,4]
    } else {
        throw("Error!");
    }
}


fn quicksort(arr) {
    if arr.len() <= 1 {
        return arr;
    }
    let pivot = arr[0];
    let left = [];
    let right = [];
    for x in arr[1..arr.len()] {
        if x < pivot {
            left.push(x);
        } else {
            right.push(x);
        }
    }
    return quicksort(left) + [pivot] + quicksort(right);
}

fn main() {
    let nums = [7,3,67,42];
    print(quicksort(nums));
}


struct Tree {
    left: Tree,
    right: Tree,
}

fn make_tree(depth) {
    if depth == 0 {return null;}
    depth -= 1;
    return Tree {left:make_tree(depth),right:make_tree(depth)};
}

fn check_tree(node) {
    if node == null { return 1; }
    return 1 + check_tree(node.left) + check_tree(node.right);
}

fn main() {
    let min_depth = 4;
    let arg = int(argv()[0]);
    let max_depth = if min_depth + 2 >= arg {min_depth + 2} else {arg};
    let stretch_depth = max_depth + 1;

    print(
        "stretch tree of depth "
        + str(stretch_depth)
        + "\t check:"
        + str(check_tree(make_tree(stretch_depth)))
    );

    let long_lived_tree = make_tree(max_depth);

    let iterations = 2 ^ max_depth;
    for depth in min_depth..stretch_depth {
        if depth % 2 != 0 {continue;}

        let check = 0;
        for i in 1..iterations+1 {
            check += check_tree(make_tree(depth));
        }

        print(
            str(iterations)
            + "\t trees of depth "
            + str(depth)
            + "\t check:"
            + str(check)
        );
        iterations /= 4;
    }

    print(
        "long lived tree of depth"
        + str(max_depth)
        + "\t check:"
        + str(check_tree(long_lived_tree))
    );
}


View more examples