Team blog

Latest news

I figure it's summer, you might think we're all at the pool enjoying the sun, but that's not quite how it is: we've been busy doing all sorts of things, such as preparing a new Ceylon IDE version that has tons of fixes, new features, improved performance that we will release shortly. We're also hard at work on the next milestone and the Ceylon SDK, but that's not why I'm writing today.

Website news

Did you know you could compile Ceylon to JavaScript? No? Well, you can, we're not only available on the JVM platform. We have this awesome JavaScript compiler that supports the same features as the JVM backend compiler. We even started shipping the SDK modules for both JVM and JavaScript backends on Herd.

Now, you may be wondering why you should care about JavaScript, and here's why: you can now try and run Ceylon code in your browser! We have an online IDE that's pretty awesome for discovering the language. Now, IDE is stretching the term a bit, but: it supports syntax colouring and auto-completion! Seriously: just try your hand at that Ctrl-Space key combo and explore the Ceylon API as you learn. No strings attached. It's still a bit slow, but our engineers are stilling hammering and soldering it as we speak, so expect it to go a lot faster once it realises how deadly we can be to slow code.

And that's not all, see? We even went ahead and plugged in that IDE in our documentation. Seriously! All the code examples in the introduction and tour have this neat and cute Try button that begs to be pressed on in order to show you that Ceylon is not just nice on paper: it's nice on your server and on your browser. How cool is that?

String[] names = { "Tom", "Dick", "Harry" };
for (name in names) {
    print("Hello, " name "!");
}

Ceylon needs you

The other thing I wanted to talk about is what you can do to help drive Ceylon forward. You already know Ceylon is open-source and everything happens in the open. We have a wonderful community working on the many parts that we call Ceylon as a whole.

Here are a few of the things I really love about the Ceylon community:

  • It's open. Not just open-source, but really really open: the discussions happen on public mailing-lists, the issue trackers are public, and everyone can pitch in for ideas, discussions, constructive criticism, opinions and advice. Obviously the core committers have more weight in the matter if there is no clear consensus on discussions, but more often than not, even fly-by commenters can have a pretty big influence on the project if they provide good ideas or comments and are willing to convince us.
  • It's a hacker-fest. Our unofficial manifesto is programming motherfucker. Obviously we love beautifuly designed things, but we hate over-engineered things and in general value more "getting things done" than "getting in the way". We could call it pragmatic programming: whatever needs to be done, we do. We have people that prefer Maven and others Ant, so some projects support both build systems. We use tools that allow everyone to work without fighting, such as git or github. As much as we can, we try to make contributions easy and agreeable — after all, if you're doing this in your free time, it should be fun!
  • It's incredibly diverse. You like client GUI work? Try the Ceylon IDE project. You like visitors, AntLR and type analysis? Try the compiler frontend (aka ceylon-spec aka the typechecker). You like generating Java AST or JavaScript? Try the compiler backends. If you're into Web things, perhaps ceylondoc (our API documentation generator), our Web IDE or even Herd (our module repository) would be your thing? Want to start a .NET backend? We can help you with that (someone already started). Want to see Ceylon run in another IDE? We will help you. Want to work on a kick-ass brand-new modern SDK? Well, why don't you? There's stuff to like for everyone's tastes.
  • It's fun, it's challenging, and it's changing the world. What good is working on something if you're waking up in the morning dreading the day ahead? We do interesting things. We do things that very few have done before. After all, not everyone writes new languages (even though it may appear to be the case), and not every new language has a scope as broad and ambitious as Ceylon. And we do it in a good spirit: it's important to have fun with your colleagues-in-open-source. And we learn a lot, we certainly do. Most of us had never done what we're working on before, so it's certainly an experience that makes you better. And best of all: we're changing the world. This is not some project that only a handful will use. Our goal is to make everyone use Ceylon, so whatever you put in there, whatever little or big thing you contribute, actually ends up being used by a lot of people. That's something to be proud of.

All of this to say: we have a great community and a great project, and we'd love to welcome you aboard! Get in touch with us and we'll help you find the project you will love, and get started with things to do: easy at first, then more and more challenging as you become more expert in the project than we are.

Come and have fun with us changing the world!

Tricks with iterable objects

Now that Ceylon has full support for mixin inheritance, we've been able to fill in all the interesting operations of the Iterable interface defined in ceylon.language. You can see the definition of Iterable here. (But be aware that, like the rest of the language module, the actual real implementation is in Java and JavaScript. The Ceylon definition is never actually compiled.)

Mapping and filtering an Iterable object

Of course, Iterable has the famous functions map(), and filter(). You can call them like this:

value filtered = "Hello Word".filter((Character c) c.uppercase);
value mapped = "Hello Word".map((Character c) c.uppercased);

(This works because a String is an Iterable<Character>.)

These operations each return Iterable—in this case, Iterable<Character>—so they don't actually allocate memory (except for a single object instantiation). If you want to actually get a new String, you need to call a function to do that:

print(string(filtered...)); //prints "HW"
print(string(mapped...)); //prints "HELLO WORLD"

As an aside, we think this is the right approach. I understand that some folks think it's better that calling filter() on a String results in a String, or that filter()ing a Set results in a Set, but I think it's quite common that the resulting container type should not be the same as the original container type. For example, it's unclear that calling map() on a Set should result in a Set, and it's certainly not correct that map()ing a String results in another String, or that map()ing a Map always results in another Map.)

Now, map() and filter() have their uses, I suppose, but in fact they're not the usual way to do mapping and filtering in Ceylon. We would really write the above code like this:

print(string(for (c in "Hello Word") if (c.uppercase) c)); //prints "HW"
print(string(for (c in "Hello Word") c.uppercased)); //prints "HELLO WORLD"

Likewise, Iterable has the methods any() and every(), but it's still usually more convenient and idiomatic to use comprehensions:

value allLowercase = every(for (c in "Hello Word") c.lowercase); //false
value someUppercase = any(for (c in "Hello Word") c.uppercase); //true

More operations of Iterable

However, there are some really useful methods of Iterable. First, find() and findLast():

value char = "Hello Word".find((Character c) c>`l`); //`o`

We can write this using a comprehension, but to be honest in this case it's slightly less ergonomic:

value char = first(for (c in "Hello World") if (c>`l`) c);

Next, sorted():

value sorted = "Hello World".sorted(byIncreasing((Character c) c.uppercased)); 
        //" deHllloorW"

Finally, fold():

value string = "Hello World".fold("", 
        (String s, Character c) 
            s.empty then c.string 
                    else s + c.string + " ");
        //"H e l l o  W o r l d"

value list = "Hello World".fold({}, 
        (Character[] seq, Character c) 
            c.letter then append(seq,c) 
                     else seq); 
        //{ H, e, l, l, o, W, o, r, l, d }

There's also two very useful attributes declared by Iterable. coalesced produces an iterable object containing the non-null elements:

value letters = { "Hello World".map((Character c) c.letter 
        then c.uppercased).coalesced... };
        //{ H, E, L, L, O, W, O, R, L, D }

The indexed attribute produces an iterable object containing the elements indexed by their position in the stream:

value entries = { "Hello World".indexed... }; 
        //{ 0->H, 1->e, 2->l, 3->l, 4->o, 5-> , 6->W, 7->o, 8->r, 9->l, 10->d }

It's quite interesting to see the declaration of these operations. For example:

shared default Iterable<Element&Object> coalesced {
    return elements(for (e in this) if (exists e) e);
}

Notice how the use of the intersection type Element&Object eliminates the need for a type parameter with a lower bound type constraint, which would be required to write down the signature of this operation in most other languages. Indeed, we use the same trick for the operations union() and intersection() of Set, as you can see here.

Set union and intersection

We let you write the union of two Sets as s|t in Ceylon, and the intersection of two Sets as s&t. Now check this out:

Set<String> strings = ... ;
Set<Integer> ints = ... ;
value stringsAndInts = strings|ints; //type Set<String|Integer>
value stringsAndInts = strings&ints; //type Set<Bottom>, since Integer&String is an empty type

That is, the type of the union of a Set<X> with a Set<Y> is Set<X|Y> and the type of the intersection of a Set<X> with a Set<Y> is Set<X&Y>. Cool, huh?

By the way, we just added similar methods withLeading() and withTrailing() to List:

value floatsAndInts = { 1, 2, 3.0 }; //type Sequence<Integer|Float>
value stuff = floatsAndInts.withTrailing("hello", "world"); //type Sequence<Integer|Float|String>

(These operations didn't make it into M3.1.)

min() and max()

Well, here's something else that's cool. Ceylon distinguishes between empty and nonempty sequences within the type system. An empty sequence is of type Empty, a List<Bottom>. A non-empty sequence is a Sequence<Element>,a List<Element>. (There's even a convenient if (nonempty) construct for narrowing a sequence to a nonempty sequence without too much ceremony.)

This lets us do something pretty cool with the signature of min() and max().

value nothingToMax = max({}); //type Nothing
value somethingToMax = max({0.0, 1.0, -1.0}); //type Float
List<Character> chars = "hello";
value maybeSomethingToMax = max(chars); //type Character?

That is, according to its signature, the max() function returns:

  • null when passed an empty sequence,
  • a non-null value when passed a nonempty sequence, or
  • a possibly-null value when passed an iterable object that we don't know is empty or nonempty.

It's important to point out that this is not some special feature built in as a special case in the type system. Nor is it in any way related to overloading. Indeed, until a couple of weeks ago I didn't even realize that this was possible. It's rather a demonstration of how expressive our type system is: in this case, the combination of intersection types, union types, and principal instantiation inheritance of generic types lets us express something within the type system that might seem almost magical. The real magic is in the declaration of the language module type ContainerWithFirstElement.

Ceylon and Ceylon IDE updated to M3.1

Ceylon M3.1 is now available for download, along with a simultaneous compatible release of Ceylon IDE. This release fixes several bugs in the recent M3 release of Ceylon, and introduces several enhancements.

To the Ceylon language module:

  • a whole suite of new operations for working with iterable objects and collections.

And to Ceylon IDE:

  • major improvements to the builder in Ceylon IDE, incorporating performance enhancements and better support for multi-project builds and for intercompilation of Ceylon with Java, and
  • cross-project refactoring.

Ceylon M3.1 is otherwise compatible with M3.

You can download the Ceylon command line distribution here:

http://ceylon-lang.org/download

Or you can install Ceylon IDE from Eclipse Marketplace or from our Eclipse update site.

Ceylon M3.1 and Ceylon IDE M3.1 require Java 7.

Source code

The source code for Ceylon, its specification, and its website, is freely available from GitHub:

https://github.com/ceylon

Issues

Bugs and suggestions may be reported in GitHub's issue tracker.

Community

The Ceylon community site includes documentation, the current draft of the language specification, the roadmap, and information about getting involved.

http://ceylon-lang.org

Acknowledgement

We're deeply indebted to the community volunteers who contributed a substantial part of the current Ceylon codebase, working in their own spare time. The following people have contributed to this release:

Gavin King, Stéphane Épardaud, Tako Schotanus, Emmanuel Bernard, Tom Bentley, Aleš Justin, David Festal, Flavio Oliveri, Max Rydahl Andersen, Mladen Turk, James Cobb, Tomáš Hradec, Michael Brackx, Ross Tate, Ivo Kasiuk, Enrique Zamudio, Julien Ponge, Julien Viet, Pete Muir, Nicolas Leroux, Brett Cannon, Geoffrey De Smet, Guillaume Lours, Gunnar Morling, Jeff Parsons, Jesse Sightler, Oleg Kulikov, Raimund Klein, Sergej Koščejev, Sjur Bakka, Chris Marshall, Simon Thum, Maia Kozheva, Shelby.

Ceylon M3 and Ceylon IDE M3 released!

Ceylon M3 "V2000" is now available for download, along with a simultaneous compatible release of Ceylon IDE. The compiler now implements almost all of the language specification, and Ceylon now fully supports both Java and JavaScript virtual machines as execution environments. The first three Ceylon platform modules are available in Ceylon Herd, the community module repository.

You can download the Ceylon command line distribution here:

http://ceylon-lang.org/download

Or you can install Ceylon IDE from Eclipse Marketplace or from our Eclipse update site.

Ceylon M3 and Ceylon IDE M3 require Java 7.

The Ceylon team hopes to release Ceylon 1.0 beta in September or October.

Language features

M3 is is an almost-complete implementation of the Ceylon language, including the following new features compared to M2:

The following language features are not yet supported in M3:

  • member class refinement and type families
  • type aliases
  • reified generics
  • user-defined annotations, interceptors, and the type safe metamodel
  • serialization

This page provides a quick introduction to the language. The draft language specification is the complete definition.

Ceylon IDE

Ceylon IDE is a complete development environment for Ceylon based on the Eclipse platform. This release of Ceylon IDE introduces:

  • support for interoperation with Java,
  • integration with Ceylon Herd,
  • many new Quick Fixes and Quick Assists, and
  • many, many bugfixes.

Ceylon IDE now automatically fetches module archives from Ceylon Herd to satisfy dependencies declared in the module descriptor.

It's now possible to write Ceylon code that calls a Java binary, navigate to its attached source code, autocomplete its declarations, hover to view its JavaDoc, etc. It's even possible to have a project that mixes Ceylon code with Java code.

Ceylon IDE M3 requires Java 7. Users of Ceylon IDE on Mac OS should install Eclipse Juno. Users on other platforms may run Ceylon IDE in either Eclipse Indigo or Eclipse Juno on Java 7. Ceylon IDE will not work if Eclipse is run on Java 6.

Support for JavaScript virtual machines and Node.js

The Ceylon command line compiler now integrates support for compilation to JavaScript. All supported language features, and all features of the Ceylon language module are supported on JavaScript.

Ceylon programs compiled to JavaScript execute on standard JavaScript virtual machines. The Ceylon command line distribution includes a launcher for running Ceylon programs on Node.js.

Interoperation with Java

Interoperation with Java code is now robust and well-tested. This release fixes a number of bugs and corner cases that affected Java interoperation in the previous release. Ceylon now requires Java 7.

Platform modules

The following platform modules are now available in Ceylon Herd:

  • ceylon.math provides arbitrary precision numeric types and numeric functions
  • ceylon.file defines an API for interacting with heirarchical filesystems
  • ceylon.process defines an API for starting native child processes.

The language module, ceylon.language is included in the distribution.

Modularity and runtime

The toolset and runtime for Ceylon are based around .car module archives and module repositories. The runtime supports a modular, peer-to-peer class loading architecture, with full support for module versioning and multiple repositories, including support for local and remote module repositories, using the local file system, HTTP, WebDAV, or even Maven repositories for interoperation with Java.

The shared community repository, Ceylon Herd is now online:

https://herd.ceylon-lang.org

Source code

The source code for Ceylon, its specification, and its website, is freely available from GitHub:

https://github.com/ceylon

Issues

Bugs and suggestions may be reported in GitHub's issue tracker.

Community

The Ceylon community site includes documentation, the current draft of the language specification, the roadmap, and information about getting involved.

http://ceylon-lang.org

Acknowledgement

We're deeply indebted to the community volunteers who contributed a substantial part of the current Ceylon codebase, working in their own spare time. The following people have contributed to this release:

Gavin King, Stéphane Épardaud, Tako Schotanus, Emmanuel Bernard, Tom Bentley, Aleš Justin, David Festal, Flavio Oliveri, Max Rydahl Andersen, Mladen Turk, James Cobb, Tomáš Hradec, Michael Brackx, Ross Tate, Ivo Kasiuk, Enrique Zamudio, Julien Ponge, Julien Viet, Pete Muir, Nicolas Leroux, Brett Cannon, Geoffrey De Smet, Guillaume Lours, Gunnar Morling, Jeff Parsons, Jesse Sightler, Oleg Kulikov, Raimund Klein, Sergej Koščejev, Chris Marshall, Simon Thum, Maia Kozheva, Shelby.

M3 status update

So it's now just over a year since my first presentation about Ceylon in Beijing. Since then, we've put together a great team, a website, the community module repository, and a full-featured IDE. And it looks like we've now implemented pretty much all the language features that I talked about in Beijing, and much more besides, for both the JVM-based backend and the JavaScript backend. Of course, while all this was happening, the language itself was evolving and the specification maturing. Phew, that sounds like a lot in just a year!

I've spent the last three days with Stef and Emmanuel in Paris, discussing a bunch of technical problems, and planning out the release of Ceylon M3. The major new features of this release are:

  • integration of the JavaScript backend into the distribution,
  • completion of support for higher-order functions including curried functions, anonymous functions, inline functions in named argument lists, and indirect invocations,
  • concrete interface members, and
  • comprehensions.

The M3 release is now planned for the second week of June.

We're also now turning our thoughts to the Ceylon SDK. By the time M3 is ready, or soon after, we'll have preview releases of several SDK modules available in Ceylon Herd, including ceylon.math, ceylon.net, and ceylon.fs. Of course, the SDK will go through a lot of growth and evolution over the coming year.

Meanwhile, we've started work on integrating Ceylon with Red Hat's open source cloud platform.

The bad news is we've decided to cancel the promised M2 release of Ceylon IDE. Sorry. The good news? We plan to release an M3-compatible IDE in June. The focus of this release will be Java interop and integration with Ceylon Herd, including:

  • automatic fetching of modules from Ceylon Herd in order to satisfy dependencies declared in the module descriptor,
  • the ability to call Java binaries from Ceylon, navigate to their attached source code, autocomplete their declarations, etc, and
  • to inter-compile Ceylon with Java, even in the same Eclipse project!

There's also some new quickfixes and autocompletions, a Create Subtype wizard, and my favorite trick, the Move to New Unit refactoring.

It would be nice to have some support for compiling for and launching to node.js in the M3 release of the IDE, but I can't promise that one.

Now that we've got so much to demo and talk about, we're trying to do more events. There's several talks coming up in June.