Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
A few weeks back, in "7 programming languages in 7 days," I intended to include Ceylon, but its creator Gavin King insisted it was too soon. Now Ceylon has released Milestone 5 with an HTTP package, making it possible for me to do the inevitable: Port Granny's Addressbook to Ceylon.
My assessment? While Ceylon is still not ready to anchor a large project, it's worth an early look. There's a lot to like about Ceylon -- as well as a number of frustrating details.
[ Epic codefest: 7 programming languages in 7 days | Learn how to work smarter, not harder with InfoWorld's roundup of all the tips and trends programmers need to know in the Developers' Survival Guide. Download the PDF today! | Keep up with the latest developer news with InfoWorld's Developer World newsletter. ]
The Ceylon IDE
The Ceylon IDE is essentially a set of plug-ins for Eclipse. While it works well for a milestone release, it is not entirely
stable and at times freezes inexplicably. Nevertheless, those with a Java background will find it comfortably familiar. The
debugger works, but imperfectly; sometimes the variables view isn't populated or you see more of Ceylon's underbelly than
your actual variables.
There is relatively good integration with the language and its features, but it lacks shine. For instance, I think the modules.ceylon file deserves its own icon or visual clue to let you know it's special.
Modules
Speaking of modules, Ceylon integrates the concept of modules and a module repository. This is probably my favorite part of
Ceylon.
If you're familiar with Java's Maven or Ivy, Perl's CPAN, or Ruby's gems, you're familiar with modules and repositories. But Ceylon improves substantially on its Java roots. Maven modules have no real relationship to Java; they're simply loaded into its class path. Ceylon makes modules a first-order member of the language and its environment independent of the build system. Unlike Java, where there are always weird bugs with how Maven views the world versus the IDE's view, this works seamlessly in Ceylon. Upgrading to a new module is simply a matter of updating your module.ceylon file.
module com.osintegrators.example.ceylon.hello '1.0.0' {
import ceylon.net '0.5';
import ceylon.dbc '0.5';
import java.jdbc '7';
import java.base '7';
}
Modules must then be imported in your runnable source code with the import statement:
import java.sql { DriverManager{ getConnection }, Connection{...}, ResultSet, Statement, PreparedStatement}
Importing
Notice that Ceylon imports a bit differently than its Java parent. There is the cosmetic issue of the bracket notation, but it goes deeper. I can import not merely classes
or packages, but also functions and values. Unlike with Java, this applies not just to static methods. In fact, Ceylon does
not have static methods, but any method can be imported.
In the sample above, I imported the getConnection method from java.sql.DriverManager. I can now call the getConnection method directly from my own method:
Connection getDbConnection() {
String userName = "granny";
String password = "granny";
String url = "jdbc:postgresql://localhost/grannydb";
forName("org.postgresql.Driver");
return getConnection (url, userName, password);
}
Naming conflicts between packages are a frustrating problem in Java. One of the most common in the early days of Java was
java.util.Date and java.sql.Date. In the case of importing both in the same class, you always had to refer to them by their fully qualified name. Ceylon imports
allow you to use aliases instead.
import java.sql { SqlDate=Date }
import java.util { Date }
Java language integration
You may notice that I imported some Java packages above. Ceylon doesn't rebuild the Java universe (at the moment). I'm using
Java's JDBC support directly. For the purpose of demonstrating Ceylon, I use the old-school Java DriverManager and JDBC driver.
I could have wired up a connection pool, but let's face it -- Granny won't need scalability for her address book.
When I use Java from Ceylon, I get most of the features of Ceylon classes and functions even if they are really Java classes
and methods. I can import individual methods, alias items, and more. One caveat: This sometimes means little conflicts with
the type system. In particular, a lot of Java stuff returns collections that appear to be the same as the Ceylon collections,
but are not. I accidentally used a Java ArrayList and wondered why I couldn't run it in a Ceylon for/each statement. For Ceylon to iterate over it, it needed to support one of Ceylon's interfaces.
It may sound contradictory, but while Java integration is one of Ceylon's best features, it's where I messed up the most. When typing familiar Java APIs in a different syntax, when the compiler says no, I have trouble "thinking" in Ceylon when typing Java APIs.
JavaScript integration
In the interest of time, I reused an existing JavaScript front end from the "7 programming languages in 7 days" article. In theory, I could have written the front end in Ceylon. This is the best argument against the idea that the future might be written entirely in JavaScript -- and in support of the idea that JavaScript is the assembly language of the future. You can write Ceylon and target Node.js,
the browser, or possibly any other JavaScript environment.
Typing in Ceylon
Ceylon is a strongly and statically typed language like Java. In fact, it is more strongly and arguably more statically typed
than Java. The one "loosening" is that types do not have to be declared on references in advance of their first use. For example,
I could type:
value header = contentType("text/html", utf8);
After this line the value reference header is a Ceylon string type. Notice I said "value reference" -- it's essentially the same as final variables in Java. They cannot
be changed. If I wanted a reference that could be changed, I'd type:
variable header = contentType("text/html", utf8);
A bigger issue with typing is the way nulls are handled. It would be very difficult to get a NullPointerException in Ceylon. The type system requires you to explicitly handle nulls, which are, in essence, a type themselves.