Metaphysical Developer

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.