Ola Bini, um dos responsáveis pelo blog de Java da editora APress comentou sobre as duas propostas para a implementação de closures na linguagem Java e os problemas que cada uma delas pode trazer (ou resolver) caso sejam adicionadas:
Se eu tivesse que escolher, não colocaria nenhuma das duas, não acho que a sintaxe do Java aguente mais uma puxada grande como essa, além do que, a maioria das bibliotecas básicas da linguagem foi escrita sem isso e vai contunuiar funcionando assim.
A turma quente do Java 5 (Neal Gafter, Gilad Bracha, Peter van der Ahé, e honorariamente o James Gosling) postou mais uma versão (simplificada, dessa vez) da proposta para Closures.
Eu ainda sou mais a favor da proposta do Gafter, mas as outras parecem ser mais simples.
Vou postar abaixo um exemplo (que obviamente não compila) do que seria possível com a proposta BGGA (Bracha, Gafter, Gosling, Ahé).
Uma coisa que incomoda no começo, mas a que você se acostuma depois, é que você tem de usar “invoke” explicitamente, em vez de usar uma closure como se fosse um nome de função.
import java.util.*;
class Cliente {
private String nome;
private int id;
public String getNome() ... bla bla bla ...
}
class TesteClosures {
/**
* Function composition, like Haskell's operator "."
* f . g (x) is equivalent to f (g (x))
* @param f the first function
* @param g the second function
* @return An instance of a function that is the composition of f and g.
*/
public static {double => double} compose (
{double => double} f,
{double => double} g) {
return new {double => double} () {
double invoke (double x) {
return f.invoke (g.invoke (x));
}
}
}
/**
* Sample of "compose"
*/
private {double => double} sin = {double x => Math.sin(x); }
private {double => double} sqrt = {double x => Math.sqrt(x); }
private {double => double} sinsqrt = compose (sin, sqrt);
private {double => double} abscos = compose (
{ x => Math.abs(x); }, { y => Math.abs (y); });
public static void main(String[] args) {
List<Cliente> clientes = new ArrayList<Cliente>();
//-- Composição de funções
//-- Ordenando com "closures"
{Cliente,Cliente=>int} ordemCrescente = { Cliente c1, Cliente c2 =>
int ret = c1.getNome().compareTo(c2.getNome());
if (ret != 0) return ret;
return c1.getId() - c2.getId();
};
{Cliente,Cliente=>int} ordemDecrescente = { Cliente c1, Cliente c2 =>
return -ordemCrescente.invoke(c1, c2);
};
// ordem crescente
clientes.sort (ordemCrescente);
// ordem decrescente
clientes.sort (ordemDecrescente);
//-- Usando um comparator tradicional e inner classes
// ordem crescente
clientes.sort (new Comparator<Cliente>() {
public int compare(Cliente c1, Cliente c2) {
int ret = c1.getNome().compareTo(c2.getNome());
if (ret != 0) return ret;
return c1.getId() - c2.getId();
}
}
// ordem decrescente
clientes.sort (new Comparator<Cliente>() {
public int compare(Cliente c1, Cliente c2) {
int ret = c1.getNome().compareTo(c2.getNome());
if (ret != 0) return - ret;
return c2.getId() - c1.getId();
}
}
}
}