Clojure vs outros Lisps [fechado]

93

A intenção da minha pergunta não é iniciar uma guerra de insultos, mas sim determinar em que circunstâncias cada idioma é "a melhor ferramenta para o trabalho".

Eu li vários livros sobre Clojure ( Programming Clojure , Practical Clojure , The Joy of Clojure e a edição Manning Early Access de Clojure in Action ) e acho que é uma linguagem fantástica. No momento, estou lendo Let Over Lambda, que lida principalmente com macros Common Lisp e, também, é uma linguagem muito interessante.

Estou não um especialista em Lisp (mais de um novato), mas esta família de línguas me fascina, assim como a programação funcional, em geral.

Vantagens do Clojure (e desvantagens de "outros"):

  • É executado no JVM.

    • A JVM é um ambiente de linguagem muito estável e de alto desempenho que atende muito bem ao sonho da Sun de "Escreva uma vez, execute [quase] em qualquer lugar". Posso escrever código no meu Macbook Pro, compilá-lo em um arquivo JAR executável e executá-lo no Linux e no Microsoft Windows com poucos testes adicionais.

    • O (Hotspot e outros) JVM suporta coleta de lixo de alta qualidade e compilação e otimização just-in-time de muito desempenho. Onde, há poucos anos, escrevi tudo o que precisava ser executado rapidamente em C, agora não hesito em fazê-lo em Java.

    • Modelo padrão, simples, multithreading. O Common Lisp tem um pacote multithreading padrão?

    • Rompe a monotonia de todos aqueles parênteses com [], {}e #{}, embora os especialistas em Common Lisp provavelmente me digam que com macros de leitor, você pode adicioná-los ao CL.

Desvantagens do Clojure :

  • É executado no JVM.
    • Sem recursão de cauda ou continuações. O Common Lisp suporta continuações? O esquema requer suporte para ambos, eu acredito.

Vantagens dos outros (Lisp comum, em particular) (e desvantagens do Clojure):

  • Macros de leitor definidas pelo usuário.

  • Outras vantagens?

Pensamentos? Outras diferenças?

Ralph
fonte
15
pessoalmente, gosto de um tipo de parênteses;) parece um código "mais limpo"
Moe
3
Pelo que li em sua lista de vantagens, acho que talvez você também goste de Erlang www.erlang.org
Peer Stritzinger
4
Clojure oferece suporte a recursão de cauda explícita por meio da forma especial "recur". Isso permite que você obtenha todos os benefícios da recursão de cauda, ​​desde que você a solicite explicitamente (a única exceção é que atualmente ela não oferece suporte a recursões de cauda mútuas entre várias funções).
Mikera
1
Clojure também suporta continuações, pelo menos no sentido de "estilo de passagem de continuação". Você está correto ao dizer que não tem continuações de primeira classe. consulte stackoverflow.com/questions/1173133/continuations-in-clojure
mikera
@mikera: Recursão de cauda em uma função. Duas funções que chamam uma à outra devem ser feitas com "trampolim", que é meio desajeitado (mas elegante à sua maneira :-)).
Ralph

Respostas:

52

Minha lista pessoal de razões para preferir Clojure a outros Lisps (ps, ainda acho que todos os Lisps são ótimos!):

  • É executado na JVM - portanto, obtém acesso automático à fantástica engenharia na própria JVM (algoritmos de coleta de lixo avançados, otimização HotSpot JIT etc.)

  • Muito boa interoperabilidade Java - fornece compatibilidade com a grande variedade de bibliotecas no ecossistema de linguagem Java / JVM. Usei Clojure como uma linguagem de "cola" para conectar diferentes bibliotecas Java com bons resultados. Como eu também desenvolvo muitos códigos Java, é útil para mim que o Clojure se integre bem com as ferramentas Java (por exemplo, eu uso Maven, Eclipse com o plugin no sentido anti-horário para meu desenvolvimento Clojure)

  • Boa sintaxe para vetores [1 2 3], mapas {:bob 10, :jane 15}e conjuntos #{"a" "b" "c"}- considero essas ferramentas essenciais para a programação moderna (além das listas, é claro!)

  • Eu pessoalmente gosto do uso de colchetes para formulários de vinculação: por exemplo (defn foo [a b] (+ a b))- acho que torna o código um pouco mais claro de ler.

  • Ênfase na programação funcional preguiçosa com estruturas de dados persistentes e imutáveis ​​- em particular toda a biblioteca Clojure principal é projetada para suportar isso por padrão

  • Excelente implementação de STM para simultaneidade multi-core. Eu acredito que Clojure tem a melhor história de simultaneidade de qualquer idioma no momento (veja este vídeo para mais detalhes do próprio Rich Hickey )

  • É um Lisp-1 (como Scheme), que pessoalmente prefiro (acho que em uma linguagem funcional faz sentido manter funções e dados no mesmo namespace)

mikera
fonte
2
1 para o STM. É, por si só, suficiente para justificar o uso de Clojure.
André Caron
2
Você ainda pode obter o STM usando a biblioteca CL-STM.
Mike Manilone
2
@ AndréCaron apenas se precisar.
direita
Se você quiser escrever um webapp simples e hospedá-lo em, digamos, um host barato de US $ 5 / mês, isso obviamente não é possível com o Clojure devido ao JVM, correto?
Hexatonic
@Hexatonic Não tenho muita experiência, mas é difícil acreditar que uma máquina em uso hoje em dia não teria um JVM.
MasterMastic
25

Lembre-se de que Clojure é uma linguagem e uma implementação (geralmente na JVM). Common Lisp é uma linguagem com mais de dez implementações diferentes. Portanto, temos uma incompatibilidade de categoria aqui. Você pode, por exemplo, comparar Clojure com SBCL.

Geralmente:

  • uma versão do Common Lisp é executada na JVM: ABCL

  • a maioria das outras implementações Common Lisp não

  • a maioria das implementações CL tem recursos multitarefa, uma biblioteca fornece uma interface comum

  • Lisp comum tem sintaxe para matrizes. A sintaxe para outros tipos de dados pode ser escrita pelo usuário e é fornecida por várias bibliotecas.

  • Common Lisp não suporta otimização de chamada final nem continuações. As implementações fornecem TCO e as bibliotecas fornecem alguma forma de continuação.

Rainer Joswig
fonte
24

Uma diferença importante entre Clojure e Common Lisp é que Clojure é mais prescritivo sobre programação funcional. A filosofia, expressões idiomáticas e, até certo ponto, linguagem / bibliotecas de Clojure encorajam fortemente e às vezes insistem que você programe de maneira funcional (sem efeitos colaterais, sem estado mutável).

O Common Lisp definitivamente suporta programação funcional, mas também permite estado mutável e programação imperativa.

Claro, há uma série de benefícios para a programação funcional, na área de simultaneidade e outras. Mas sendo tudo o mais igual, também é bom ter a escolha de qual abordagem você deseja usar para cada situação. Clojure não proíbe completamente a programação imperativa, mas é menos compatível com esse estilo do que o Common Lisp.

Charlie Flowers
fonte
3
@Charlie Flowers: Acredito que no Common Lisp seja possível programar em um estilo "puramente funcional" (suporte de estrutura de dados persistente, etc.), mas requer disciplina. Corrigir?
Ralph de
2
Apenas um esclarecimento sobre "sem efeitos colaterais, sem estado mutável" - Clojure tem estado mutável (refs, átomos, agentes etc. são todos mutáveis), mas requer que você o acesse de uma forma controlada (ou seja, por meio dos mecanismos STM e transações relacionadas atualização semântica)
mikera
5
@mikera: exceto que Clojure depende do uso de bibliotecas Java para ser utilizável, e todas essas bibliotecas requerem um estilo imperativo e estão cheias de efeitos colaterais. Descobri que as ligações com Java são um presente envenenado ...
André Caron
1
@Andre - claro, se você decidir usar uma biblioteca que requer estado mutável e semântica imperativa, você terá que gerenciar isso. Isso não é diferente de se você acessasse essa biblioteca de qualquer outro idioma. Mas você tem duas opções decentes: a) Não use essas bibliotecas - você pode escrever um código perfeitamente bom em puro Clojure ou b) envolver a complexidade da interface com essas bibliotecas em uma interface funcional no estilo Clojure agradável, que geralmente é fácil com macros ou agentes etc. No geral, descobri que a capacidade de aproveitar as bibliotecas Java é um benefício muito maior do que um problema.
Mikera de
4
@mikera: as bibliotecas têm um benefício. Estou apenas apontando que o uso de bibliotecas Java (este é um dos principais objetivos de Rich Hickey para a linguagem) realmente vai contra o aspecto "mais funcional do que outros lisps" do Clojure. Meu comentário pretendia significar: "a menos que você reescreva / empacote essas bibliotecas, você obterá um código de aparência imperativa e não se beneficiará das partes mais legais do Clojure".
André Caron
10

Aqui está um bom vídeo com uma comparação de Scheme (Racket principalmente) e Clojure .

Para ser justo, Racket tem sintaxe de açúcar (material de leitor adicional) para tipos de dados também (#hash, #, colchetes, etc.)

Além disso, a única maneira de Clojure fazer uma chamada final adequada é usar recur, essa é a desvantagem de compilar para JVM.

Observe que recuré a única construção de loop que não consome pilha no Clojure. Não há otimização de chamada final e o uso de chamadas automáticas para looping de limites desconhecidos é desencorajado. recuré funcional e seu uso na posição final é verificado pelo compilador. ( Formulários Especiais ).

Daniil
fonte
Link está morto, eu acho.
nawfal
1
@nawfal Acho que consertei
Daniil
6
Link está morto (de novo?)
Throw Away Account
1
Parece que o vídeo desse link pode ser encontrado aqui: vimeo.com/22675078 .
PIB2
Também existe trampolinepara chamadas de cauda.
HappyFace de