Em muitos artigos, descrevendo os benefícios da programação funcional, vi linguagens de programação funcional, como Haskell, ML, Scala ou Clojure, conhecidas como "linguagens declarativas" distintas de linguagens imperativas como C / C ++ / C # / Java. Minha pergunta é o que torna as linguagens de programação funcional declarativas e não imperativas.
Uma explicação frequentemente encontrada que descreve as diferenças entre a programação declarativa e a imperativa é que, na programação imperativa, você diz ao computador "Como fazer algo" em oposição a "O que fazer" em linguagens declarativas. O problema que tenho com essa explicação é que você está constantemente fazendo as duas coisas em todas as linguagens de programação. Mesmo que você desça para a montagem de nível mais baixo e ainda esteja dizendo ao computador "O que fazer", instrua a CPU a adicionar dois números, não o instruirá sobre como executar a adição. Se formos para o outro extremo do espectro, uma linguagem funcional pura de alto nível como Haskell, você estará dizendo ao computador como realizar uma tarefa específica, é isso que o seu programa é uma sequência de instruções para realizar uma tarefa específica que o computador não sabe realizar sozinho. Entendo que linguagens como Haskell, Clojure etc. são obviamente mais altos que C / C ++ / C # / Java e oferecem recursos como avaliação lenta, estruturas de dados imutáveis, funções anônimas, currying, estruturas de dados persistentes, etc. programação funcional possível e eficiente, mas eu não os classificaria como linguagens declarativas.
Uma linguagem declarativa pura para mim seria uma que é composta inteiramente apenas por declarações; um exemplo dessas linguagens seria CSS (Sim, eu sei que CSS tecnicamente não seria uma linguagem de programação). O CSS contém apenas declarações de estilo usadas pelo HTML e Javascript da página. O CSS não pode fazer mais nada além de fazer declarações, não pode criar funções de classe, ou seja, funções que determinam o estilo a ser exibido com base em algum parâmetro, você não pode executar scripts CSS, etc. Isso para mim descreve uma linguagem declarativa (observe que eu não disse declarativa linguagem de programação ).
Atualizar:
Estive brincando com o Prolog recentemente e, para mim, o Prolog é a linguagem de programação mais próxima de uma linguagem totalmente declarativa (pelo menos na minha opinião), se não for a única linguagem de programação totalmente declarativa. Para elaborar a programação no Prolog é feita fazendo declarações que afirmam um fato (uma função predicada que retorna true para uma entrada específica) ou uma regra (uma função predicada que retorna true para uma determinada condição / padrão com base nas entradas), regras são definidos usando uma técnica de correspondência de padrões. Para fazer qualquer coisa no prólogo, você consulta a base de conhecimento substituindo uma ou mais das entradas de um predicado por uma variável e o prólogo tenta encontrar valores para as variáveis para as quais o predicado é bem-sucedido.
Meu ponto de vista é que, no prólogo, não há instruções imperativas, você basicamente diz (declara) ao computador o que sabe e depois pergunta (faz perguntas) sobre o conhecimento. Nas linguagens de programação funcional, você ainda está fornecendo instruções, como pegar um valor, chamar a função X e adicionar 1, etc., mesmo que você não esteja manipulando diretamente os locais da memória ou escrevendo a computação passo a passo. Eu não diria que a programação em Haskell, ML, Scala ou Clojure é declarativa nesse sentido, embora eu possa estar errado. É adequada, verdadeira, pura programação funcional declarativa no sentido que descrevi acima.
(let [x 1] (let [x (+ x 2)] (let [x (* x x)] x)))
(espero que você entenda isso, Clojure). Minha pergunta original é o que torna isso diferente deste int. x = 1; x += 2; x *= x; return x;
Na minha opinião, é basicamente o mesmo.