Mesmo assim, acho que vale a pena investigar o que pode ser reaproveitado. Vou começar com grep e map, que são funções que processam listas. Grep é usado para selecionar itens de uma lista e map para mapear uma lista para outra.
Em Perl, grep recebe dois parâmetros: um bloco de código (ou uma expressão) e uma lista. Para cada elemento da lista, grep executa o bloco ou avalia a expressão. Se o resultado for verdadeiro, o elemento é adicionado à lista de saída. O exemplo abaixo é do manual do ActivePerl:
@foo=grep(!/^#/,@bar);# weed out comments
Este código mostra uma chamada a grep com uma expressão regular (seleciona linhas que não começam com #) e uma lista @bar.
Java, infelizmente, não tem funções propriamente ditas, então vai ser preciso escrever grep como um método estático:
import java.util.*;
public class Grep {
public static <T> List<T> grep(List<T> in, Grepping<T> mapping) {
List<T> out=new ArrayList<T>();
for(T t : in) {
if(mapping.map(t)) {
out.add(t);
}
}
return out;
}
}
O código usa generics, então parece mais complicado do que é. Em poucas palavras, ela recebe uma lista de elementos do tipo T e um mapeamento para elementos desse mesmo tipo; ela retorna uma lista do mesmo tipo T.
A classe Grepping é bastante simples e já fornece um comportamento default (sempre retorna true):
public class Grepping<T> {
public boolean map(T t) {
return true;
}
}
Suponha que seja preciso selecionar um grupo de pessoas, conforme a idade. Precisamos de uma classe para pessoas e outra para lista de pessoas.
public class Pessoa {
private String nome;
private int idade;
private char sexo;
public Pessoa(String nome, int idade, char sexo) {
this.nome=nome;
this.idade=idade;
this.sexo;
}
public String nome() {
return nome;
}
public int idade() {
return idade;
}
public char getSexo() {
return sexo;
}
}
public class PessoaList extends ArrayList<Pessoa> {
}
Com isso, posso escrever um mapeamento por idade.
public class PessoaPorIdade extends Grepping<Pessoa> {
private int limiar;
public PessoaPorIdade(int limiar) {
this.limiar=limiar;
}
public boolean map(Pessoa p) {
return p.getIdade()>=limiar;
}
}
Então, seu eu quiser selecionar todos os maiores de 18 anos, posso fazer o seguinte:
maiores=Grep.grep(pessoas, new PessoasPorIdade(18));
Nas situações em que o mapeamento não precisa ser parametrizado, gosto de criar um membro estático assim:
public class PessoaGrepping {
public static final Grepping<Pessoa> MULHERES=
new Grepping<Pessoa>() {
public boolean map(Pessoa p) {
return p.getSexo()='F';
}
}
public static final Grepping<Pessoa> HOMENS=
new Grepping<Pessoa>() {
public boolean map(Pessoa p) {
return p.getSexo()='M';
}
}
}
Usar os mapeamentos é simples:
mulheres=Grep.grep(pessoas, PessoaGrepping.MULHERES);
Para simular a função map, basta criar uma classe Mapping, que retorne uma instância de T no lugar de um booleano:
import java.util.*;
public class Map{
public static <T> List<T> map(List<T> in, Mapping<T> mapping) {
List<T> out=new ArrayList<T>();
for(T t : in) {
T r=mapping.map(t);
if(r!=null) {
out.add(r);
}
}
return out;
}
}
public class Mapping<T> {
public T map(T t) {
return t;
}
}
O resultado não é tão simples como o que se pode escrever em Perl, mas já é um avanço. Quando Java tiver closures, certamente será possível escrever código ainda mais compacto para executar essas funções.
Nenhum comentário:
Postar um comentário