Tenho pensado nessa pergunta há muito tempo, mas realmente não consegui encontrar a resposta no Google, bem como uma pergunta semelhante no Stackoverflow. Se houver uma duplicata, sinto muito por isso.
Muitas pessoas parecem dizer que escrever compiladores e outras ferramentas de linguagem em linguagens funcionais como OCaml e Haskell é muito mais eficiente e fácil do que escrevê-los em linguagens imperativas.
Isso é verdade? E em caso afirmativo - por que é tão eficiente e fácil escrevê-los em linguagens funcionais em vez de em uma linguagem imperativa, como C? Além disso - uma ferramenta de linguagem em uma linguagem funcional não é mais lenta do que em alguma linguagem de baixo nível como C?
Respostas:
Freqüentemente, um compilador trabalha muito com árvores. O código-fonte é analisado em uma árvore de sintaxe. Essa árvore pode então ser transformada em outra árvore com anotações de tipo para realizar a verificação de tipo. Agora você pode converter essa árvore em uma árvore contendo apenas elementos básicos da linguagem (convertendo notações sintáticas semelhantes a açúcar em uma forma não açúcar). Agora você pode realizar várias otimizações que são basicamente transformações na árvore. Depois disso, você provavelmente criaria uma árvore em alguma forma normal e, em seguida, iteraria nessa árvore para criar o código de destino (montagem).
A linguagem funcional tem recursos como correspondência de padrões e bom suporte para recursão eficiente, o que facilita o trabalho com árvores, por isso são geralmente consideradas boas linguagens para escrever compiladores.
fonte
Muitas tarefas do compilador são correspondência de padrões em estruturas de árvore.
OCaml e Haskell têm recursos de correspondência de padrões poderosos e concisos.
É mais difícil adicionar correspondência de padrões a linguagens imperativas, pois qualquer valor que esteja sendo avaliado ou extraído para corresponder ao padrão deve estar livre de efeitos colaterais.
fonte
Um fator importante a considerar é que uma grande parte de qualquer projeto de compilador é quando você pode hospedar o compilador e "comer sua própria comida de cachorro". Por esse motivo, quando você olha para linguagens como OCaml, onde são projetadas para pesquisa de linguagem, elas tendem a ter ótimos recursos para problemas do tipo compilador.
Em meu último trabalho do tipo compilador, usamos OCaml exatamente por esse motivo enquanto manipulávamos o código C, era a melhor ferramenta para a tarefa. Se o pessoal do INRIA tivesse construído o OCaml com prioridades diferentes, talvez não fosse uma escolha tão boa.
Dito isso, as linguagens funcionais são a melhor ferramenta para resolver qualquer problema, logo, segue-se logicamente que são a melhor ferramenta para resolver esse problema específico. QED.
/ me: retorna às minhas tarefas Java com um pouco menos de alegria ...
fonte
Basicamente, um compilador é uma transformação de um conjunto de código para outro - da fonte para IR, de IR para IR otimizado, de IR para montagem, etc. Este é precisamente o tipo de coisa para a qual as linguagens funcionais são projetadas - uma função pura é apenas uma transformação de uma coisa para outra. As funções imperativas não têm essa qualidade. Embora você possa escrever esse tipo de código em uma linguagem imperativa, as linguagens funcionais são especializadas para isso.
fonte
Veja também
Padrão de design F #
FP agrupa coisas 'por operação', enquanto OO agrupa coisas 'por tipo', e 'por operação' é mais natural para um compilador / interpretador.
fonte
Uma possibilidade é que um compilador tende a ter que lidar com muito cuidado com uma série de casos esquivos. Acertar o código geralmente fica mais fácil com o uso de padrões de design que estruturam a implementação de uma forma paralela às regras que implementa. Freqüentemente, isso acaba sendo um design declarativo (correspondência de padrões, "onde") em vez de imperativo (sequenciamento, "quando") e, portanto, mais fácil de implementar em uma linguagem declarativa (e a maioria deles são funcionais).
fonte
Parece que todos perderam outro motivo importante. É muito fácil escrever uma linguagem específica de domínio incorporada (EDSL) para analisadores que se parecem muito com (E) BNF em código normal. Os combinadores de analisadores como Parsec são muito fáceis de escrever em linguagens funcionais usando funções de ordem superior e composição de funções. Não só mais fácil, mas muito elegante.
Basicamente, você representa os analisadores genéricos mais simples como funções e tem operações especiais (normalmente funções de ordem superior) que permitem compor esses analisadores primitivos em analisadores mais complicados e específicos para sua gramática.
Esta não é a única maneira de fazer frameworks parer, é claro.
fonte