Metaphysical Developer

Scala: The Successor to the Throne

Posted in Languages by Daniel Ribeiro on July 29, 2009

It has been a while since Java was the sole language running over a JVM. Scala is another such language which gained a lot attention recently for being used to scale Twitter‘s backend. Scala differs from most other languages that run on the JVM, such as Groovy, JRuby and Jython, as it is statically typed. This means that, similar to Java and C#, the types must be known at compile time. Scala is usually introduced as being both OO and functional. While this statement is true (and daunting, as many people are uncomfortable with the f*** word), it fails to grasp the important aspects of Scala.

Among the most direct benefits of using Scala feature:

  • Compatible with Java. Kinda obvious (as so are all the other 200+ languages over the JVM), but it is such an important feature that should not be overlooked. This means that Scala can use all Java libraries and frameworks. Which shows respect for people’s and companies investment on the technology.
  • Joint Compilation. This means that, like Groovy, Scala classes are compiled to Java classes, and therefore can be used on Java projects (even by java classes on the same project they are defined). Even if your team decides to make the complete move towards Scala, this can be useful integrating with dynamic languages via JSR 223.
  • Type Inference. If the compiler can guess the type (and it usually can), you don’t have to tell it. This allows Scala code to be as concise as dynamic languages, while still being type safe.
  • Implicit conversion allows you to achieve in a type safe way what extension methods do for C# and open classes (mostly) do for ruby. That is: add methods to types you might not have not defined yourself (such as strings, lists, integers). This is one of the features that make Scala DSL friendly.
  • Object immutability is encouraged and easy to accomplish. Scala even comes with immutable collections built-in.
  • Getters and Setters are automatically generated for you. If you don’t want them (if you only want setters for example), you have to explicitly make them private. Which is not a problem, as the common case is to want them.
  • Scala has first-order functions and implements an enumeration protocol (with the iterable trait), which helps keeping code clearer, more concise, and brings several other benefits.
  • The Actor programming model eases up the development of highly concurrent applications.
  • Exceptions don’t have to be explictly caught or thrown. It can be argued that having checked exceptions does more harm than good.

These features alone would be enough to make Scala a very interesting language, and worth being heralded as the current heir apparent to the Java throne by one of JRuby’s creator, Charles Nutter (a view somewhat shared by Neal Gafter). Or even worth of being endorsed both by Groovy’s creator, James Strachan, and by the inventor of Java, James Gosling.  Nonetheless Scala is deep, and there are several exciting advanced features that allow developers to be more productive. But learning such features before getting a good grasp the basics can be quite frustrating, more so without a good supporting literature (such as IBM‘s, Aritma‘s, Jonas Bonér‘s, Daniel Spiewak‘s, Sven Efftinge‘s, the official one, and several others). However it quite is feasible, not only encouraged, to delve into deeper concepts as you need them.

Even though Scala has academic roots (as it shows on its papers page, and some advanced concepts these tackle), Scala has been successfully used on enterprise projects, besides Twitter, such as Siemens, Électricité de France Trading and WattzOn.

Besides all the good points, Scala does have some rough edges. Even though many people are working on overcoming them, they are likely to be relevant on the short term:

  • Incipient IDE support. As Lift‘s author expressed, IDEs for Scala, while undergoing a lot of development, are not what they are for Java. There is poor refactoring support, code completion and unit test integration. Not to mention the fact that most framework support tools will not play nicely with Scala. This can also put off some newcomers, as an IDE can help people learn the language. On the other hand, Martin Folwer relativizes this IDE situation, as a language that allows you to be more productive can more than make up for the lack of sophisticated tools.
  • Joint Compilation is not supported by most IDEs as well. Again, likely to change as Scala grows in popularity.
  • Immutability on a class is not really immutability, since referring objects may not be immutable themselves. And there is no way at the moment to ensure the whole object graph is immutable.
  • Making JSR 223 work perfectly with Scala can be challenging. On the other hand, making it work good enough is quite attainable.
  • Scala doesn’t support metaprogramming. This can be worked around by combining it with dynamic languages, such as Ruby (following a polyglot programming approach), but if you are going to do heavy use of metaprogramming, than using a whole different language may be a better solution (Fan is another static type language that runs over the JVM, similar to Scala, that has metaprogramming support).
  • Frameworks that expect Java source, such as the client-side GWT, will not play nicely with Scala (note that people have made Scala work with GWT on the server-side though). However there is an ongoing project that will translate Scala into Java source.
  • The syntax and some concepts are bit different from Java, such as: inverted type declaration order, underscore being used instead of wildcards, asterisks and default values, many kinds of nothing, no static methods (you need to use singleton objects instead) and other minor things. The documentation walks through this quite nicely though, but keep in mind that it is not an automatic transition from writing Java to writing Scala code.

As Joe Armstrong said, the need for languages that allow developers to easily make use of CPUs with multiple cores will only increase as such CPUs become cheaper and gain more and more cores. Scala is quite suited for such task, while Java’s development is stuck dealing with issues that come from being widely deployed, uncertanties of how open it will be in the future and political issues with some of its main contributors. Given the situation, Scala seems to fit quite nicely the role of the successor to Java’s throne.

Literal Collections In Java

Posted in Languages by Daniel Ribeiro on May 23, 2009

Terse ways to express Literal Collections such as Maps and Lists can be useful when building an Internal DSL. Java is famous for not having any facility to craft those. It does have literal object arrays, but these are a bit awkward when nesting, which is usually what you are going to do when employing this technique. But using variable arguments functions can supplement this deficiency quite nicely.

Below I show some ways to achieve this using an useful import static from http://code.google.com/p/fluentjava/: import static org.fluentjava.FluentUtils.*. I also comapare with the original ruby examples from Martin Fowler’s DSL Book.

  • Lists and Maps in Java
  • alist("computer",
      alist("processor", map(pair("cores", 2), pair("type", "i386"))),
      alist("disk", map(pair("size", 150))),
      alist("disk", map(
       pair("size", 78),
       pair("speed", 7200),
       pair("interface", "sata")))
      );
  • Lists and Maps in Ruby
  • [:computer,
     [:processor, {:cores => 2, :type => :i386}],
     [:disk, {:size => 150}],
     [:disk, {:size => 75, :speed => 7200, :interface => :sata}]
    ]
  • Just Lists in Java
  • alist("computer",
      alist("processor", alist("cores", 2), alist("type", "i386")),
      alist("disk", alist("size", 150)),
      alist("disk", alist("size", 78), alist("speed", 7200),
        alist("interface", "sata")));
  • Lists and Pairs in Java
  • alist("computer",
     alist("processor", pair("cores", 2), pair("type", "i386")),
     alist("disk", pair("size", 150)),
     alist("disk",
      pair("size", 78), pair("speed", 7200), pair("interface", "sata"))
     );
  • Just Lists In Ruby
  • [:computer,
     [:processor,
      [:cores, 2,],
      [:type, :i386]],
     [:disk,
      [:size, 150]],
     [:disk,
      [:size, 75],
      [:speed, 7200],
      [:interface, :sata]]]
  • Using a symbol as a vararg function (Java only)
  • $("computer",
     $("processor", $("cores", 2), $("type", "i386")),
     $("disk", $("size", 150)),
     $("disk", $("size", 78), $("speed", 7200), $("interface", "sata"))
    );
    
    private FluentList<Object> $(Object... args) {
       return alist(args);
    }

From the comparison, it is easy to see that ruby is bit more appropriate for this technique (and so are other languages such as python, perl and lisp). However, some cleverly defined (or imported) functions can help Java code benefit from it as well.

Tagged with: , , , ,

Closures, Collections and some Functional Programming

Posted in Languages by Daniel Ribeiro on May 2, 2009

Collection libraries are quite common today in almost all languages, and we are very glad that every non trivial piece of software does not require us to define again what a List is, neither what a Tree is. Also, we do not have to keep on reimplementing basic algorithms such as sort. Some languages even provide literal ways to define the most commonly useful collections, such as lists and maps.

Closures (also known as blocks and lamba expressions) are also common on several languages (Java and C++ being notable exceptions), even though it only started becoming more mainstream with Ruby. Besides being useful on creating DSLs , they allow us to easily define callback procedures on GUIs, declare transactions, readily craft simple implementations of Visitors and Commands patterns, enable controlled lazy evaluation on languages that do not natively support it, refactor complex switch statements to a simple map leading to Closures, and so on.

Even though closures and collections are useful on their own, when combined they allow us to abstract iteration mechanisms. Smalltalk is notable for blending closures and collections in a category of methods that form a protocol called enumeration protocol. For instance (examples in ruby, that also features an enumeration protocol, similar to smalltalk), we can rewrite this:

novels = []
for b in books
  if b.novel?
    novels << b
  end
end

Into this:

books.select {|b| b.novel?}

This way the code gets clearer, more concise and more simple, while encapsulating the actual iteration algorithm, which allow us to reuse the very same filter whether the books are coming from a list, from a file, from a database, or from a SOAP request. Not only that, but it allows us to refactor several filters of books into one line methods:

class Books
  def novels()
    return @books.select {|b| b.novel?}
  end

  def older_than(year)
    return @books.select {|b| b.age > year}
  end

  def name_starts_with(str)
    return @books.select {|b| b.name[0, 1] == str}
  end
end

But abstract iteration mechanisms are more than just filtering. Common enumeration protocols (such as those from Ruby and Smalltalk) features several methods to detect elements, to create new maps with a function, sort elements, get the maximum and minimum elements (using a closure as a definition of comparison) and so on. Many of these are inpsired by functions orginally defined on functional programming languages, such as fold and map.

The encapsulation of iteration mechanism is also usefull when we want to start using coarse-grained parallelism, such as proposed by Fork Join (which, ironically is written in a language that does not have closures) . That is: you had a sequential code, and with very little alteration, you can get a parallel/distributed one (while being cautious of side effects). In our example: Books#novels could be very well selecting the novels in separate threads, and joining them all together. It would only be a matter of changing the implementation of @books.

Concluding: Closures and Collections allows us to improve code by:

  • making it more concise
  • making it clearer
  • making it more suitable to refactoring
  • making sure you Don’t Repeat Youself
  • enabling you to easily turn sequential code into parallel

Considering that all of these points are too good to let go, and considering that java 7 will not get closures and that not only are anonymous inner classes really closures but also too verbose, I started a little project called Fluent Java. This project, among other things, brings up the enumeration protocol to java, while still keeping it terse, and easy to use (Fork Join integration is planned as well).

Edit: Java might get simplified closures after all (at least, for now, it is planned). But still too early to say regarding how this was already pulled off once, and Oracle has some issues to work through with Sun, which may push JDK7 to being released early.

Edit (22 Sep 2010): Yes, it got pulled away. From the Chief Architect of the Java Platform Group: It’s time for … Plan B. Scala has them though…

Fluent Code

Posted in Languages by Daniel Ribeiro on April 12, 2009

Fluent style of coding is quite important on internal Domain Specific Languages (DSLs) on languages that support OO. One of the key aspects of a fluent interface is method chaining, which allows the developer to reduce noise (the amount of repeated text) on the code by invoking several methods on the same object, one after the other. Just as in the good old fashioned Don’t Repeat Yourself (DRY) spirit, less noise.

However, fluent code is not only appropriate for DSLs. It can greatly improve code readability and intention revealing even on simple tasks, such as building a complex object.

For instance, let’s take a simple example of configuring an email. You can do lots of things to it, such as configure the sender, the subject, the body, and so on. In Java, such code would become:

new Email()
    .from("me@gmail.com")
    .subject("metaphysics")
    .to("everybody@gmail.com")
    .cc("CIA@usa.gov")

Instead of the usual, full of noise:

Email email = new Email();
email.from("me@gmail.com");
email.subject("metaphysics");
email.to("everybody@gmail.com");
email.cc("CIA@usa.gov");

A problem arises when the class you want to use method chaining on classes that are not already fluent and you do not have write access. Maybe you are using it from a library or from a Framework you have to use. On languages with static typing such as Java, the only solution is to create yourself a static wrapper (more specifically, a proxy) around it, and just delegate the methods to the real implementation.

On languages with support for method lookup alteration and interception, such as Ruby’s missing_method and Smalltalk’s doesNotUnderstand:, you can make such wrapper a general one. Example of such in ruby:

class Email
  attr_accessor :to, :from, :subject, :cc
end

class Wrapper
  def initialize(wrapped)
    @wrapped = wrapped
  end

  def method_missing(m, *args, &block)
    setter = m.to_s + '='
    if @wrapped.respond_to?(setter)
      @wrapped.send(setter, *args, &block)
    else
      raise NoMethodError
    end
    return self
  end
end

mail = Email.new
Wrapper.new(mail).
  from('me@gmail.com').
  subject('metaphysics').
  to('everybody@gmail.com').
  cc('CIA@usa.gov')

The beauty is: Wrapper is general. You can take any object of any class you like and, just like that, use a fluent interface around it. You can do this in Smalltalk as well, but Smalltalk is naturally fluent, because of the semicolon:

email <- Email new
        from: 'me@gmail.com';
        subject: 'metaphysics';
        to: 'everybody@gmail.com';
        cc: 'CIA@usa.gov';
        yourself.

Regarding Java language, even though you cannot make a fluent universal wrapper as you can do in ruby (dynamic proxies can’t change the interface, neither can Aspectj), there are some good perspectives ahead:

  • Chained Invocations on methods that return void. Unlikely to make the cut into the jdk 7
  • This Type: which just makes it clearer that a interface is fluent. Also, eases up the fact that subclasses will return its type on fluent methods defined on the parent.
Tagged with: , , , ,
Follow

Get every new post delivered to your Inbox.