Simplificando, as restrições significam que há menos maneiras corretas de organizar as coisas, e as funções de primeira classe facilitam o fatoramento de coisas como estruturas de loop. Pegue o loop desta resposta , por exemplo:
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
String string = iterator.next();
if (string.isEmpty()) {
iterator.remove();
}
}
Essa é a única maneira imperativa e segura em Java para remover um elemento de uma coleção enquanto você está iterando. Há muitas maneiras que parecem muito próximas, mas estão erradas. As pessoas que desconhecem esse método às vezes passam por maneiras complicadas para evitar o problema, como iterando uma cópia.
Não é terrivelmente difícil tornar esse genérico, portanto ele funcionará mais do que apenas coleções Strings
, mas sem funções de primeira classe, você não pode substituir o predicado (a condição dentro do if
), portanto esse código tende a ser copiado e colado e modificado ligeiramente.
Combine funções de primeira classe que lhe dão a capacidade para passar o predicado como um parâmetro, com a restrição de imutabilidade que o torna muito chato se você não faz, e você vem com blocos de construção simples, como filter
, como neste código Scala isso faz a mesma coisa:
list filter (!_.isEmpty)
Agora pense no que o sistema de tipos verifica para você, no momento da compilação, no caso do Scala, mas essas verificações também são feitas por sistemas de tipos dinâmicos na primeira vez em que você o executa:
list
deve ser algum tipo de tipo que suporte o filter
método, ou seja, uma coleção.
- Os elementos de
list
devem ter um isEmpty
método que retorne um booleano.
- A saída será uma coleção (potencialmente) menor com o mesmo tipo de elementos.
Uma vez que essas coisas foram verificadas, que outras maneiras restam para o programador estragar? Esqueci acidentalmente o !
que causou uma falha extremamente óbvia no caso de teste. Esse é praticamente o único erro disponível para ser cometido, e eu o cometi apenas porque estava traduzindo diretamente do código que testou a condição inversa.
Esse padrão é repetido repetidamente. As funções de primeira classe permitem refatorar as coisas em pequenos utilitários reutilizáveis com semântica precisa, restrições como a imutabilidade fornecem o ímpeto para fazê-lo e a verificação de tipo dos parâmetros desses utilitários deixa pouco espaço para estragar tudo.
Obviamente, tudo depende do programador saber que a função simplificadora filter
já existe e ser capaz de encontrá-la ou reconhecer o benefício de criar você mesmo. Tente implementar isso sozinho em qualquer lugar usando apenas recursão da cauda, e você estará de volta no mesmo barco de complexidade que a versão imperativa, apenas pior. Só porque você pode escrevê-lo de maneira muito simples, não significa que a versão simples seja óbvia.