A maioria das linguagens convencionais, incluindo linguagens de programação orientada a objetos (OOP), como C #, Visual Basic, C ++ e Java, foram projetadas para oferecer suporte principalmente à programação imperativa (procedural), enquanto as linguagens Haskell / gofer são puramente funcionais. Alguém pode elaborar qual é a diferença entre essas duas formas de programação?
Sei que depende dos requisitos do usuário para escolher o modo de programação, mas por que é recomendável aprender linguagens de programação funcionais?
oop
functional-programming
Swapnil Kotwal
fonte
fonte
Respostas:
Definição: Uma linguagem imperativa usa uma sequência de instruções para determinar como atingir um determinado objetivo. Diz-se que essas declarações alteram o estado do programa à medida que cada uma é executada.
Exemplos: Java é uma linguagem imperativa. Por exemplo, um programa pode ser criado para adicionar uma série de números:
Cada instrução altera o estado do programa, desde a atribuição de valores a cada variável até a adição final desses valores. Usando uma sequência de cinco instruções, o programa é explicitamente informado sobre como adicionar os números 5, 10 e 15.
Linguagens funcionais: o paradigma de programação funcional foi criado explicitamente para oferecer suporte a uma abordagem funcional pura para a solução de problemas. A programação funcional é uma forma de programação declarativa.
Vantagens das funções puras: A principal razão para implementar transformações funcionais como funções puras é que as funções puras são composíveis: ou seja, independentes e sem estado. Essas características trazem vários benefícios, incluindo o seguinte: Maior legibilidade e capacidade de manutenção. Isso ocorre porque cada função é projetada para realizar uma tarefa específica, dados seus argumentos. A função não depende de nenhum estado externo.
Desenvolvimento reiterativo mais fácil. Como o código é mais fácil de refatorar, as alterações no design geralmente são mais fáceis de implementar. Por exemplo, suponha que você escreva uma transformação complicada e perceba que algum código é repetido várias vezes na transformação. Se você refatorar através de um método puro, poderá chamá-lo à vontade sem se preocupar com os efeitos colaterais.
Teste e depuração mais fáceis. Como funções puras podem ser mais facilmente testadas isoladamente, você pode escrever um código de teste que chama a função pura com valores típicos, casos de borda válidos e casos de borda inválidos.
Para pessoas OOP ou idiomas imperativos:
Linguagens orientadas a objetos são boas quando você tem um conjunto fixo de operações e, à medida que seu código evolui, você adiciona principalmente coisas novas. Isso pode ser conseguido adicionando novas classes que implementam métodos existentes e as classes existentes são deixadas em paz.
Linguagens funcionais são boas quando você tem um conjunto fixo de coisas e, à medida que seu código evolui, você adiciona principalmente novas operações às coisas existentes. Isso pode ser conseguido adicionando novas funções que computam com os tipos de dados existentes e as funções existentes são deixadas em paz.
Contras:
Depende dos requisitos do usuário para escolher a maneira de programar, para que haja danos apenas quando os usuários não escolherem a maneira correta.
Quando a evolução segue o caminho errado, você tem problemas:
fonte
Aqui está a diferença:
Imperativo:
... E assim por diante ...
Declarativa, da qual funcional é uma subcategoria:
... E assim por diante ...
Resumo: em linguagens imperativas, você informa ao computador como alterar bits, bytes e palavras na memória e em que ordem. Nos funcionais, dizemos ao computador o que são coisas, ações etc. Por exemplo, dizemos que o fatorial de 0 é 1 e o fatorial de qualquer outro número natural é o produto desse número e o fatorial de seu antecessor. Não dizemos: Para calcular o fatorial de n, reserve uma região de memória e armazene 1 lá, multiplique o número nessa região de memória pelos números 2 para ne armazene o resultado no mesmo local e, no final, a região da memória conterá o fatorial.
fonte
A maioria das linguagens modernas é, em graus variados, imperativa e funcional, mas para entender melhor a programação funcional, é melhor usar um exemplo de linguagem funcional pura como Haskell, em contraste com o código imperativo em linguagem não tão funcional como java / c #. Eu acredito que é sempre fácil explicar pelo exemplo, então abaixo está um.
Programação funcional: calcule fatorial de n ie n! ou seja, nx (n-1) x (n-2) x ... x 2 X 1
Observe que Haskel permite sobrecarregar a função até o nível do valor do argumento. Agora abaixo está um exemplo de código imperativo em crescente grau de imperatividade:
Essa leitura pode ser uma boa referência para entender como o código imperativo se concentra mais em como parte, estado da máquina (i in for loop), ordem de execução, controle de fluxo.
O exemplo posterior pode ser visto como código java / c # lang de maneira grosseira e como primeira parte como limitação da própria linguagem, em contraste com Haskell, para sobrecarregar a função por valor (zero) e, portanto, pode-se dizer que não é uma linguagem funcional purista, por outro mão, você pode dizer que suporta prog funcional. até certo ponto.
Divulgação: nenhum dos códigos acima é testado / executado, mas espero que seja bom o suficiente para transmitir o conceito; Também gostaria de receber comentários por qualquer correção :)
fonte
return n * factorial(n-1);
?n * (n-1)
A Programação Funcional é uma forma de programação declarativa, que descreve a lógica da computação e a ordem de execução é completamente enfatizada.
Problema: quero mudar esta criatura de cavalo para girafa.
Cada item pode ser executado em qualquer ordem para produzir o mesmo resultado.
A programação imperativa é processual. Estado e ordem são importantes.
Problema: quero estacionar meu carro.
Cada etapa deve ser executada para chegar ao resultado desejado. Puxar para dentro da garagem enquanto a porta está fechada resultaria em uma porta quebrada.
fonte
A programação funcional é "programação com funções", onde uma função tem algumas propriedades matemáticas esperadas, incluindo transparência referencial. A partir dessas propriedades, outras propriedades fluem, em particular etapas familiares de raciocínio possibilitadas pela substituibilidade que levam a provas matemáticas (isto é, justificando a confiança em um resultado).
Daqui resulta que um programa funcional é meramente uma expressão.
Você pode ver facilmente o contraste entre os dois estilos observando os lugares em um programa imperativo em que uma expressão não é mais referencialmente transparente (e, portanto, não é construída com funções e valores, e não pode ser parte de uma função). Os dois lugares mais óbvios são: mutação (por exemplo, variáveis) outros efeitos colaterais fluxo de controle não local (por exemplo, exceções)
Nesta estrutura de programas como expressões, composta de funções e valores, é construído todo um paradigma prático de linguagens, conceitos, "padrões funcionais", combinadores e vários sistemas de tipos e algoritmos de avaliação.
Pela definição mais extrema, quase qualquer linguagem - mesmo C ou Java - pode ser chamada de funcional, mas geralmente as pessoas reservam o termo para linguagens com abstrações especificamente relevantes (como fechamentos, valores imutáveis e auxílios sintáticos, como a correspondência de padrões). No que diz respeito ao uso da programação funcional, envolve o uso de funções e cria código sem efeitos colaterais. usado para escrever provas
fonte
O estilo de programação imperativa foi praticado no desenvolvimento web desde 2005 até 2013.
Com a programação imperativa, escrevemos código que listava exatamente o que nosso aplicativo deveria fazer, passo a passo.
O estilo de programação funcional produz abstração através de maneiras inteligentes de combinar funções.
Há menção de programação declarativa nas respostas e, em relação a isso, direi que a programação declarativa lista algumas regras que devemos seguir. Em seguida, fornecemos o que chamamos de estado inicial de nosso aplicativo e permitimos que essas regras definam como o aplicativo se comporta.
Agora, essas descrições rápidas provavelmente não fazem muito sentido, então vamos percorrer as diferenças entre programação imperativa e declarativa, percorrendo uma analogia.
Imagine que não estamos construindo software, mas fazemos tortas para ganhar a vida. Talvez sejamos padeiros ruins e não sabemos como fazer uma torta deliciosa do jeito que deveríamos.
Então, nosso chefe nos dá uma lista de instruções, o que sabemos como receita.
A receita nos dirá como fazer uma torta. Uma receita é escrita em um estilo imperativo assim:
A receita declarativa faria o seguinte:
1 xícara de farinha, 1 ovo, 1 xícara de açúcar - Estado inicial
Regras
As abordagens imperativas são caracterizadas por abordagens passo a passo. Você começa com o passo um e vai para o passo 2 e assim por diante.
Você acaba com algum produto final. Então, fazendo esta torta, pegamos esses ingredientes, misturamos, colocamos em uma panela e no forno e você conseguiu seu produto final.
Em um mundo declarativo, é diferente. Na receita declarativa, separaríamos nossa receita em duas partes separadas, comece com uma parte que liste o estado inicial da receita, como as variáveis. Portanto, nossas variáveis aqui são as quantidades de nossos ingredientes e seu tipo.
Tomamos o estado inicial ou os ingredientes iniciais e aplicamos algumas regras a eles.
Portanto, tomamos o estado inicial e as repassamos repetidamente por essas regras até prepararmos uma torta de morango pronta para comer ou qualquer outra coisa.
Portanto, em uma abordagem declarativa, precisamos saber como estruturar adequadamente essas regras.
Portanto, as regras que podemos examinar nossos ingredientes ou declarar, se misturados, colocá-los em uma panela.
Com o nosso estado inicial, isso não corresponde porque ainda não misturamos nossos ingredientes.
A regra 2 diz que, se não estiverem misturados, misture-os em uma tigela. Ok, sim, esta regra se aplica.
Agora temos uma tigela de ingredientes misturados como nosso estado.
Agora aplicamos esse novo estado às nossas regras novamente.
Então a regra 1 diz que se os ingredientes forem misturados, coloque-os em uma panela, ok, sim, agora a regra 1 se aplica, vamos fazê-lo.
Agora temos esse novo estado em que os ingredientes são misturados e em uma panela. A regra 1 não é mais relevante, a regra 2 não se aplica.
A regra 3 diz que se os ingredientes estiverem em uma panela, coloque-os no forno, ótimo essa regra é o que se aplica a esse novo estado, vamos fazê-lo.
E acabamos com uma deliciosa torta de maçã quente ou o que seja.
Agora, se você é como eu, pode estar pensando: por que ainda não fazemos uma programação imperativa? Isso faz sentido.
Bem, para fluxos simples, sim, mas a maioria dos aplicativos da Web possui fluxos mais complexos que não podem ser capturados adequadamente pelo design de programação imperativa.
Em uma abordagem declarativa, podemos ter alguns ingredientes iniciais ou estado inicial
textInput=“”
, como uma única variável.Talvez a entrada de texto comece como uma sequência vazia.
Tomamos esse estado inicial e o aplicamos a um conjunto de regras definidas em seu aplicativo.
Se um usuário digitar texto, atualize a entrada de texto. Bem, agora isso não se aplica.
Se o modelo for renderizado, calcule o widget.
Bem, nada disso se aplica; portanto, o programa irá esperar um evento acontecer.
Então, em algum momento, um usuário atualiza a entrada de texto e, em seguida, podemos aplicar a regra número 1.
Podemos atualizar isso para
“abcd”
Assim, acabamos de atualizar nossas atualizações de texto e de texto, a regra número 2 não se aplica, a regra número 3 diz que se a entrada de texto for atualizada, o que acabou de ocorrer, em seguida, renderizamos novamente o modelo e, em seguida, voltamos à regra 2, que diz que o modelo é renderizado , calcule o widget, ok vamos calcular o widget.
Em geral, como programadores, queremos lutar por projetos de programação mais declarativos.
O imperativo parece mais claro e óbvio, mas uma abordagem declarativa é muito bem dimensionada para aplicativos maiores.
fonte
• Línguas imperativas:
Execução eficiente
Semântica complexa
Sintaxe complexa
Simultaneidade é programador projetado
Testes complexos, sem transparência referencial, têm efeitos colaterais
• Idiomas funcionais:
Semântica simples
Sintaxe simples
Execução menos eficiente
Os programas podem se tornar automaticamente simultâneos
Testes simples, com transparência referencial, sem efeitos colaterais
fonte
Eu acho que é possível expressar a programação funcional de uma maneira imperativa:
if... else
/switch
instruçõesExistem enormes problemas com essa abordagem:
A programação funcional, tratando funções / métodos como objetos e adotando apatridia, nasceu para resolver os problemas que eu acredito.
Exemplo de usos: aplicativos de interface como Android, iOS ou lógicas de aplicativos da Web, incl. comunicação com o back-end.
Outros desafios ao simular programação funcional com código imperativo / processual:
Também acredito que, no final do dia, o código funcional será traduzido em código de montagem ou de máquina, que é imperativo / processual pelos compiladores. No entanto, a menos que você escreva assembly, como humanos escrevendo código com linguagem de alto nível / legível por humanos, a programação funcional é a maneira de expressão mais apropriada para os cenários listados.
fonte
Sei que esta pergunta é mais antiga e outros já a explicaram bem, gostaria de dar um exemplo de problema que explica o mesmo em termos simples.
Problema: Escrevendo a tabela 1.
Solução: -
Por estilo imperativo: =>
Por estilo funcional: =>
Explicação no estilo Imperativo, escrevemos as instruções mais explicitamente e que podem ser chamadas da maneira mais simplificada.
Onde, como no estilo Funcional, as coisas auto-explicativas serão ignoradas.
fonte