Ceylon - gregorymorrison/euler1 GitHub Wiki

Ceylon is a Java replacement introduced in 2011 by Red Hat and Gavin King, author of the ORM Hibernate. It's designed to run on both Java and JavaScript. It has static typing and strong typing.

Here’s a standard iterative example of Euler1 in Ceylon, which looks very much like Java. Note the keyword variable - objects in Ceylon are immutable by default unless declared using variable:

// Euler1 in Ceylon

Integer euler1(Integer size) {
    variable Integer retval = 0;
    for (i in 1..size) {
        if (i%3 == 0 || i%5 == 0) {
                retval += i;
        }
    }
    return retval;
}

print ("``euler1(999)``");

One of Ceylon's fundamental data structures is the collection, which implements the Iterable interface. This interface has a rich set of functions, including the Functional map/filter/fold. These functions are built right into the language - nice! Ceylon also has built-in support for other Functional programming features, such as immutability (see variable above), first-class functions, anonymous functions (note the arguments passed to map and filter), and currying. Here's Euler1 implemented with map/filter/fold:

// Euler1 in Ceylon

Integer euler1(Integer size) {
    Iterable<Integer> ints = (1..size);
    return ints
        .map((Integer i) => i)
        .filter((Integer i) => i%3==0 || i%5==0);
        .fold(0, plus<Integer>);
}

print ("``euler1(999)``");

I must admit that I had significant frustration with Ceylon's type system in the above example. Ceylon is very strict, and it took me a few hours to figure out what types I needed to declare to make the runtime happy.

Ceylon has comprehensions - syntactic sugar for the imperative for-loop/if-then, or the functional map/filter. Very nice!

// Euler1 in Ceylon

Integer euler1(Integer size) {
    return [for (i in 1..size) if (i%3==0 || i%5==0) i].fold(0, plus<Integer>);
}

print ("``euler1(999)``");

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. Here we pass around a list of integers, and peel off the first one each iteration. Note here the use of  Iterable's methods first, rest and nonempty:

// Euler1 in Ceylon

Integer euler(Integer[] ints, Integer acc) {
    if (nonempty ints) {
        Integer n = ints.first%3 == 0 || ints.first%5 == 0 then ints.first else 0;
        return euler(ints.rest, acc+n);
    } else {
        return acc;
    }
}

Integer euler1(Integer size) {
    return euler(1..size, 0);
}

print ("``euler1(999)``");

Here’s another version using a Quicksort-based algorithm. Here we recursively break the list up in half and then reassemble it. Instead of sorting each half, though, we’ll filter the pivot value, converting it to 0 if it’s not divisible. Here, euler() returns euler() calculated on the half of the list before the pivot element, euler() calculated on the half of the list after the pivot element, and the pivot element or 0, all added together.

// Euler1 in Ceylon

Integer euler(Integer[] ints) {
    if (ints.empty) { return 0; }

    Integer pivot = ints.size / 2;

    Integer pivotval;
    Integer? _pivotval = ints[pivot];
    if (exists _pivotval) {
        if (_pivotval%3 == 0 || _pivotval%5==0) {
            pivotval = _pivotval;
        } else {
            pivotval = 0;
        }
    } else {
        pivotval = 0;
    }

    Integer pre;
    if (0 < pivot) {
        pre = euler( ints[0..pivot-1] );
    } else {
        pre = 0;
    }

    Integer post;
    if (pivot+1 < ints.size) {
        post = euler( ints[pivot+1..ints.size-1] );
    } else {
        post = 0;
    }

    return pre + pivotval + post;
}

Integer euler1 (Integer size) {
    return euler(1..size);
}

print ("``euler1(999)``");

Here’s one more – an elegant algorithm based on an observation by little Carl Friedrich Gauss. It operates in O(1) constant time. Don’t sweat it if this seems inscrutable; click the blog link above for an explanation.

// Euler1 in Ceylon

Integer mysum (Integer n, Integer size) {
    return ((size/n)^2 + size/n) * n / 2;
}

Integer euler1(Integer size) {
        return mysum(3,size) + mysum(5,size) - mysum(15,size);
}

print ("``euler1(999)``");

Overall, Ceylon feels like a very well-designed language, with excellent documentation. If you'd like to try it out, they have an online editor/interpreter available at http://try.ceylon-lang.org/.

⚠️ **GitHub.com Fallback** ⚠️