I had originally decided that I wasn’t going to spent a lot of time coming up with new features for saturn but would just reimplement neptune. However, as I might have expected, I just can’t help myself. Many of the “new” ideas are things we discussed back when we designed neptune, though, so it’s more “outtakes” than actual new material.

The thing I’ve been most happy about adding so far is also the very simplest: a compact syntax for creating intervals. In C, Java and even neptune, you iterate over an interval by using the standard for loop:

for (int i = 0; i < n; i++) ...

This is unfortunate for more than one reason. First of all, it's too much boilerplate. 90% of for loops that iterate over a sequence of numbers are the same except for the name of the loop variable and the limit to iterate up to. Below, I've underlined the parts of the statement that aren't boilerplate:

for (int i = 0; i < n; i++) ...

That's actually less than half the code! Also, the loop variable is mentioned three times which gives ample opportunity to get it wrong. If you're like me, for instance, and have the variable i hardwired in your brain but need to iterate for a different variable there's a very real risk that you'll end up writing

for (int j = 0; i < n; i++) ...

The third problem with this kind of for loops is a classic: the limit is evaluated for each iteration. In rare cases that is exactly what you need. More often, however, it is either unnecessary (and may waste execution time) or just plain wrong.

In saturn it takes just one method to fix this: the .. method on the class Integer:

class Integer {
operator ..(that) {
return new Interval(this, that);

With this method, writing from .. to creates a new open interval from from to to. What can you do with an interval? Most importantly, iterate through it:

for (i : 0 .. n) {
// whatever

Almost all the boilerplate code is gone. The iteration variable is only mentioned once and the limit is only evaluated once, when the interval is created. And since the receiver of the .. method is known at compile time, the compiler can optimize away the creation of the interval with no visible consequences other than a performance improvement. Yessir!

Another change I've made is to add more shorthands for occurrences of expressions. In neptune we had two syntaxes for blocks: one for statement blocks and one for blocks whose body was just a single expression:

// statement block
fun (x) {
var str = x.to_string();

// expression block
fun (x) -> x * 2

In saturn, I've decided to introduce this distinction more places. Possibly the most visible place I've added this is methods -- there is now a compact syntax for methods that return the value of a single expression:

class Point {
var x, y;
norm() -> sqrt(x * x + y * y);

In neptune (and Java and ...) you would have had to write something like

norm() {
return sqrt(x * x + y * y);

Regular "statement methods" still exist but this makes it easier to write short methods and having short methods is generally a Good Thing. Also, to me, it just sort of looks right in a way I can't explain.

I'm also considering adding a new form of for statement along the same lines:

var ints = for (i : 0 .. 100) -> 2 * i;
// ints = [0, 2, 4, ..., 198]

As with a regular for statement, a for expression evaluates its body repeatedly but the expression collects the values of the body in a new collection. It's essentially a list comprehension

ints = [ i * 2 | i <- [0 .. 100] ]

but with an untraditional syntax that has a number of advantages: it's very easy to explain in terms of for statements and the variable definitions occur syntactically before their use. In the Haskell-like syntax above, i is being used before it's defined which I find non-obvious and difficult to read.

There you have it: three new features, two of which have already been implemented. I haven't figured out all the details of how the new for expression should work but I'm sure I can take inspiration from existing list comprehension mechanisms. I'm also working towards an alpha release of the compiler and runtime but currently you'll have to get it through CVS from saturn-language at sourceforge to try it out.

One Response to Details

Leave a Reply

Your email address will not be published. Required fields are marked *