Todas as linguagens de programação possuem ifs (exceto Prolog). Parecem inevitáveis, mas, na maior parte dos casos, é possível eliminar muitos ifs sem dificuldades. Vou mostrar como.
Uma técnica muito simples (e talvez a mais antiga encarnação da programação incondicional) é o array de ponteiros para funções. É tão simples, que pode ser usada em Assembly, como um array de endereços.
Em C, posso declarar um array de funções que recebem dois ints e retornam int assim:
int (*p[4])(int x, int y);
Posso invocar qualquer uma das funções assim:
resultado=(*p[op]) (i, j);
E com isso evito a seguinte seqüência particulamente perniciosa de ifs:
if(op==0) {
resultado=somar(i, j);
} else if(op==1) {
resultado=subtrair(i, j);
} else if(op==2) {
resultado=dividir(i, j);
} else ...
Perl oferece uma das sintaxes mais simples para declarar estruturas de dados; posso declarar o array e as funções de uma só vez de maneira bastante compacta.
my @ops = (
sub { $_[0]+$_[1] },
sub { $_[0]-$_[1] },
sub { $_[0]/$_[1] },
sub { $_[0]*$_[1] },
);
my $resultado=$ops[2]->(3,2);
Java, infelizmente, não possui funções, mas elas podem ser simuladas com subclasses. Como no Perl, é possível criar as subclasses e o array ao mesmo tempo, mas a sintaxe é muito mais complicada.
Operador[] ops=new Operador[] {
new Operador() {
public int eval(int i, int j) {
return i+j;
}
},
new Operador() {
public int eval(int i, int j) {
return i-j;
}
},
//etc, etc, etc...
};
int resultado=ops[2].eval(3,2);
Usar um hash (array associativo) é só um caso especial dessa técnica. Nenhuma linguagem permite um exemplo tão compacto como Perl:
my %ops = (
'+' => sub { $_[0]+$_[1] },
'-' => sub { $_[0]-$_[1] },
'/' => sub { $_[0]/$_[1] },
'*' => sub { $_[0]*$_[1] },
);
my $resultado=$ops{'+'}->(3,2);
E esta foi a introdução à programação incondicional!
Isto aqui: sub { @_[0]+@_[1] }
ResponderExcluirnão seria assim? sub { $_[0]+$_[1] }
Ou seja, da mesma forma que $ops[2] acessa o array @ops.
Aliás, forinti é "for int i"?
Ainda não descobri o que é alquerubim :-P
Bem notado, já corrigi. Mas é interessante como o código funcionou mesmo com o erro. Acontece que em Perl, um array avaliado em contexto escalar vira o valor do último elemento. @_[0] é o splice de um elemento (o 0-ésimo), que no contexto escalar vira o valor do único elemento. @_[1,5] retornaria um array com os elementos de 1 a 5. Funcionava, mesmo sem ser o que eu pretendia.
ResponderExcluirSim, forinti nasceu de uma longa jornada programando Java.
E Alquerubim é uma aldeia em Portugal, perto do rio Vouga, de onde vieram meus avós.
É, eu sabia que funcionava dos dois jeitos, com @ ou $, mas tinha aprendido (na decoreba mesmo) que o certo era com $. Sabes se há casos em que o uso do @_[0] causaria um comportamento inesperado?
ResponderExcluirClaro, se eu tivesse pesquisado no Google eu saberia o que é Alquerubim, mas achava que fosse um jogo de palavras e nem pesquisei hahaha
Boa pergunta. Tem umas funções que fazem coisas diferentes conforme o tipo do parâmetro, mas se o valor vai sempre ser imediatamente usado num contexto escalar, não deve acontecer nada.
ResponderExcluir