Sunday, February 26, 2012

Funcito: wrap Java methods for FP libraries

On and off, I've been collaborating with my friend, Kevin Welker, on an open-source project: Funcito. This is really his baby, but it has been great fun to be involved (more to come in another post).

Executive Summary

From the FAQ, Funcito is a Java library that simplifies access to functional programming APIs by wrapping Java methods as the function-type objects defined in those libraries. It reduces boilerplate now, without waiting for changes in Java 8.

The syntax (and internals) is influenced by Mockito, the popular mocking framework. However, Funcito is not aimed at testing.

It supports specific interfaces in Google Guava, Functional Java, and Jedi-core. See the project page for details.

Example in straight Google Guava

Here is example code for using Google Guava, using a List of Song objects.

The setup is simply populating the list:

public void init() {
// List<Song> songs is a member
songs.add( new Song("Help!", "The Beatles", new BigDecimal(1.29) ) );
songs.add( new Song("You Had Time", "Ani DiFranco", new BigDecimal(0.99) ) );
songs.add( new Song("Shoot to Thrill", "AC/DC", new BigDecimal(0.89) ) );
songs.add( new Song("Back in Black", "AC/DC", new BigDecimal(0.89) ) );
songs.add( new Song("Indie Song", "Obscure Band", BigDecimal.ZERO ) );
songs.add( new Song("Demo Track", "College Jam", BigDecimal.ZERO ) );
}

Here is an example test, using a predicate method on Song, isFree(), to filter for free songs:

public Collection<Song> filterFreeSongs() {
// boilerplate alert!
Predicate<Song> isFreePredicate = new Predicate<Song>() {
public boolean apply(Song s) { return s.isFree(); }
};

Collection<Song> freeSongs = Collections2.filter(songs, isFreePredicate);

// size == 2 in example
return freeSongs;
}


Note the typical pattern to build a Predicate, even though the object is simply calling a boolean method. Funcito addresses precisely this issue.

Example with Funcito

Using the same setup, here is the same test using Funcito. Note the proxy object, CALLS_TO_SONG:

// member of class
// using static import of Funcito's callsTo
private Song CALLS_TO_SONG = callsTo(Song.class);

public Collection<Song> filterFreeSongs() {
// using static import of Funcito's predicateFor
Predicate<Song> isFreePredicate = predicateFor(CALLS_TO_SONG.isFree());

Collection<Song> freeSongs = Collections2.filter(songs, isFreePredicate);

// size == 2
return freeSongs;
}


Less boilerplate, with improved readability and a fluid syntax!

The Upshot

If you are using straight-up FP libraries in Java, and want to reduce some of the boilerplate, check out Funcito. It's lightweight with minimal dependencies (either CGLib or Javassist), and can help you wrap up simple Java methods.