Some functional programming techniques
The 1.1 release will allow support of the Scala programming language. One great thing (but not the only one) about Scala is that it is a mixed imperative — functional language that allow to solve a lot of problem in a functional way.
But now, what if you prefer keep using Java with play ? Could we bring some of the nice features of Scala to Java as well ? So let’s me introduce the new LambdaJ support in play.
The main purpose of lambdaj is to partially eliminate the burden to write (often nested and poorly readable) loops while iterating over collections. From the LambdaJ website:
How many times have you read or written the same two or three lines of code that frequently seem to go together, and even though they operate on different objects, feel like the same thing? And how often these repetitions involve some sort of collections iteration or more generically manipulation? These repetitions in the code is something that developers eventually learn to filter out and ignore when reading code, once they figure out where the interesting parts are placed. But even if the developers get used to it, it slows them down. Code like that is clearly written for computers to execute, not for developers to read.
lambdaj is a library that makes easier to address this issue by allowing to manipulate collections in a pseudo-functional and statically typed way. In our experience to iterate over collection, especially in nested loops, is often error prone and makes the code less readable. The purpose of this library is to alleviate these problems employing some functional programming techniques but without losing the static typing of java. We impose this last constraint to make refactoring easier and safer and allow the compiler to do its job.
Let’s use lambdaj
We will start with a fresh application that allow to display a Car catalog. The Car model class will just be defined as:
package models;
import play.*;
import play.db.jpa.*;
import javax.persistence.*;
import java.util.*;
@Entity
public class Car extends Model {
public String name;
public String brand;
public int numberOfViews;
public Date lastViewed;
@Transient
public double price;
public Car viewed() {
lastViewed = new Date();
numberOfViews++;
return this;
}
}
And let’s write a simple action that retrieve all these cars:
public static index() {
List<Car> cars = Car.find().fetch();
render(cars);
}
Now in the page it would be great to be able to order all these cars by brand. So we need to extract all the brand from the car list. Let’s do it the lambdaj way:
List<String> brands = collect(cars, on(Car.class).brand);
This line will iterate over all the retrieved cars, collect all the brands and feed them to the returned list. The very cool things is that we are able to express that stuff in a pure statically typed way.
Now we need to filter this list to remove brand duplication:
Collection<String> brands = selectDistinct(
collect(cars, on(Car.class).brand)
);
Very easy.
Batching method calls
We want to cound each time a Car has been viewed, and remember the last viewed time. As we already have the viewed() method that update the Car objects we just need to call this method on each retrieved car. Again, let’s do it the lambdaj way:
forEach(cars).viewed();
This line will iterate over each car object of the cars list and call the viewed() method on each.
And because we modified the state of the persistent objects, we need to save them. So rewrite it as:
forEach(cars).viewed().save();
Using closures
Hugh? But Java doesn’t have closure! Wait, lambdaj partially fill this lack by a feature that allow to define, in its traditional DSL style, first-class functions with free variables.
Let’s say we have a PriceWatcher utility able to fetch in real time the price of each car.
package models;
public class PriceWatcher {
public void setPrice(Car car) {
// retrieve the correct price here
car.price = currentPrice;
}
}
Because this data need to be in real time we don’t want store it in the database. Before displaying the car list we need to create a PriceWatcher object and ask it to resolve the current price of each car. Again, let’s do it the lambdaj way:
PriceWatcher priceWatcher = new PriceWatcher();
Car.forEach(cars); {
of(priceWatcher).setPrice(var(Car.class));
}
We define a function with a free variable, and then ask to the Car class to call them for each element of the cars list.
The final action code
Using all these good lambdaj stuff, we can finally write the index action in a very expressive fashion:
public static void index() {
List<Car> cars = Car.find().fetch();
// Collect brands
Collection<String> brands = selectDistinct(
collect(cars, on(Car.class).brand)
);
// Set all these cars viewed
forEach(cars).viewed().save();
// Update the prices
PriceWatcher priceWatcher = new PriceWatcher();
Car.forEach(cars); {
of(priceWatcher).update(var(Car.class));
}
render(cars, brands);
}