Brat - gregorymorrison/euler1 GitHub Wiki

Brat, introduced in 2010, is a toy language designed to be simple and fun. It's a dynamically-typed language which runs as bytecodes on the Lua VM. Here's an example of Euler1, which took me only minutes to write upon my first look at the language. It uses a list comprehension in a functional style that looks fairly influenced by Ruby. Notice that a function implicitly returns the value of its last statement:

# Euler1 in Brat

euler1 = { size |
    ints = 1.to(size).select { x | x % 3 == 0 || x % 5 == 0 }
    ints.reduce :+
}

p euler1 999

What does a simple imperative version look like? Here's one where we explicitly decrement a counter in a loop:

# Euler1 in Brat

euler1 = { x |
    result = 0
    while {x > 0} {
        true? x % 3 == 0 || x % 5 == 0
            { result = result + x }
        x = x - 1
    }
    result
}

p euler1 999

Brat brags that it's so simple it has no keywords. Wait, what? Well, the only fixed syntax is its operators; everything else is implemented as an object or function redefinable at runtime. Okay, so there is a base set of functions like p (print) and while, but still it's pretty small.

In Brat, everything is either an object or a function, and classes are prototype-based - merely dictionaries of objects. Here’s an example - we instantiate a new object which has two properties, size and result, and one method, solve. We then call the solve method. Yes, it’s contrived - OOP is way overkill for so simple a problem, but let's try anyway:

# Euler1 in Brat

euler1 = new

euler1.size = 999
euler1.result = 0

euler1.solve = {
    ints = 1.to(my.size).select { x | x % 3 == 0 || x % 5 == 0 }
    my.result = ints.reduce :+
}

euler1.solve
p euler1.result

Next is a functional version that uses tail recursion with an accumulator. One of the main points here is that the function euler is deterministic – it will always return the same output for a given input. This is accomplished in part by the absence of any variable manipulation – there are instead only functions which return values. The other main point is that this recursion uses tail call optimization – it’s written in such a way that an intelligent compiler can optimize its stack usage to be O(n) instead of O(n!). In English, this means that your program will probably not crash even for hugely recursive calls.

# Euler1 in Brat

euler = { n, acc |
    true? n <= 1
        { acc }
        { true? n % 3 == 0 || n % 5 == 0
            { euler n - 1, acc + n }
            { euler n - 1, acc }}}

euler1 = { n | euler n, 0 }

p euler1 999

Brat tries to be flexible in its syntax regarding requirement of braces, parens, commas, etc, but it just ends up feeling flaky. It took me about an hour to figure out how to get the above to work.

As expected, functions are first-class members that can be passed around like objects. Brat uses an arrow operator, ->, to indicate functions that should be referenced instead of performed. More documentation can be found here: https://github.com/presidentbeef/brat/wiki/The-Complete-Brat

Disappointingly, I tried to install Brat from source but failed. Luckily, Brat's web site contains an interactive code editor, complete with samples, which lets you immediately play with the language. Nothing to install - brilliant! To run, just put your code in the online editor and click Try it!:

233168

I was going to write more different kinds of examples of Euler1 in Brat, but I think I broke the online interpreter. I was playing with first-class functions, and I think I accidentally issued an unbounded recursion routine. The site crashed, and it's now been down over a day. Well, that's it for Brat!