Li vários livros e aprendi com a experiência que otimizar o código até o ponto em que ele é inescrutável ou encontrar uma solução extremamente rápida, mas extremamente complexa para um problema, não é desejável quando se trabalha em equipe ou mesmo quando você está trabalhando. sozinho e precisa entender sua solução inteligente algum tempo depois.
Minha pergunta é: a recursão deve ser tratada da mesma maneira? O programador médio entende a recursão facilmente e, portanto, deve-se usá-la com impunidade ou o programador médio não entende muito bem a recursão e deve ficar longe dela por causa da produtividade geral da equipe?
Eu sei que existem respostas simples de: "Qualquer programador que não entenda a recursão não vale um grão de sal, então não se preocupe com eles", mas eu queria saber se todos vocês têm alguma experiência no mundo real que gostariam de ter. compartilhar que iluminaria a questão mais do que a opinião que acabei de mencionar.
fonte
Respostas:
Eu diria que o programador médio entende a recursão perfeitamente. De fato, se o programador se formou em Ciência da Computação ou Engenharia de Software, isso é praticamente garantido. É verdade que existem alguns programadores muito abaixo da média por aí, mas você não os quer em sua equipe.
Nesse caso, a distinção entre um programador médio e um bom programador é saber quando usar recursão e quando não usar. E isso depende do problema que está sendo resolvido E da linguagem usada para resolvê-lo.
Se você estiver usando uma linguagem de programação funcional, a recursão é uma solução natural e eficiente para uma ampla gama de problemas. (Regras de otimização da recursão da cauda!)
Se você estiver usando uma linguagem processual simples ou OO, a recursão pode ser ineficiente e problemática devido ao excesso de pilha. Portanto, em alguns casos, você escolheria uma solução iterativa em vez de uma solução recursiva. No entanto, em outros casos, a solução recursiva é muito mais simples e elegante que a (possivelmente mais eficiente) solução iterativa seria a "muito inteligente". (Por exemplo, se o problema exigir retorno, construção ou caminhada de árvores / gráficos, etc., a recursão geralmente será mais simples.)
fonte
Alguns problemas são naturalmente recursivos. Encontrar uma solução iterativa nesses casos pode realmente ser mais desajeitado e complexo do que os recursivos. Um bom exemplo é qualquer algoritmo que precise percorrer uma estrutura hierárquica em árvore, o que é uma tarefa não incomum na programação.
TL; versão DR: Não.
fonte
A recursão é um princípio fundamental na maioria das linguagens de programação funcionais. A iteração (loop) em linguagens funcionais geralmente é realizada por recursão.
Ultimamente, as linguagens funcionais viram um renascimento, devido à necessidade de lidar com mais núcleos de processador; linguagens funcionais ajudam a obter esse tipo de simultaneidade, fornecendo maneiras de melhor raciocinar sobre seu programa sem a complexidade envolvida no bloqueio de estruturas mutáveis.
fonte
Alguns problemas, como percorrer uma estrutura em árvore (percorrer, digamos, uma estrutura de diretórios inteira, em vez de, digamos, procurar um nó específico da Árvore B), são ideais para usar a recursão; os equivalentes não recursivos geralmente simplesmente adicionam a complicação de gerenciar sua própria pilha.
Nesses casos, a recursão é a solução melhor, mais simples e mais fácil de entender.
fonte
Eu diria que use a recursão onde for apropriado, mas sempre procure maneiras de evitar recursões explícitas.
Por exemplo, se você achar necessário atravessar manualmente uma estrutura em árvore, sim, você deve usar a recursão. Se alguém é burro o suficiente para não entender uma travessia recursiva da árvore, não fará nem cabeça nem cauda da versão iterativa.
Mas uma opção melhor é usar um iterador que abstraia a recursão até o ponto em que tudo que você vê é "Eu executo essa operação em tudo na árvore".
fonte
Recursão, é o mecanismo mais simples do ponto de vista de limpeza de código. Se a velocidade é absolutamente essencial, talvez você possa usar uma matriz 2D de parâmetros de problemas. Gerar um processo filha é simplesmente anexar outro item à matriz. Certa vez, fiz um solucionador tridiagonal de montador, que foi um grande negócio naquela época. O contexto necessário por instância era de 8 palavras por nível, e cada subproblema tinha um terço do tamanho do anterior. Essa "biblioteca" era popular apenas porque superava todas as outras implementações existentes. Mas, essa é uma situação bastante rara na programação, portanto você não precisa sucumbir à "otimização prematura", apenas porque esta solução está disponível. Obviamente, para algumas coisas, seu terrível exagero, como o exemplo da recursão 101 "calcula o fatorial". Mas para a maioria dos aplicativos,
Eu tenho um verificador ortográfico simples que uso em um aplicativo (onde quero dar dicas sobre como corrigir erros de ortografia menores), onde calculo a "distância" entre duas strings, permitindo exclusões e adições. Isso leva a uma estrutura de árvore potencialmente grande e os galhos são cortados, pois só nos preocupamos com correspondências fechadas. Com recursão, são talvez vinte linhas de código (eu tenho as versões Fortran e C). Eu acho que seria confuso caso contrário. Heck, era muito mais fácil programar / verificar erros, do que pensar nessa árvore!
fonte
Eu entendo, mas nunca o usei explicitamente. Eu acho que qualquer um que se autodenomina um programador deve saber ou aprender o que é tanto quanto precisa saber o que é a pilha e a pilha. Ei, todo mundo precisa saber como o mínimo / máximo funciona no jogo da velha, por meio de recursão sofisticada.
fonte