web-dev-qa-db-fra.com

Clojure vs autres Lisps

Le but de ma question n'est pas non de déclencher une guerre des flammes, mais plutôt de déterminer dans quelles circonstances chaque langue est "le meilleur outil pour le travail".

J'ai lu plusieurs livres sur Clojure ( Programmation Clojure , Practical Clojure , The Joy of Clojure , et l'édition Manning Early Access de Clojure in Action ), et je pense que c'est un langage fantastique. Je lis actuellement Let Over Lambda qui traite principalement des macros LISP communes, et, lui aussi, est un langage très intéressant.

Je ne suis pas un expert LISP (plutôt un débutant), mais cette famille de langages me fascine, tout comme la programmation fonctionnelle en général.

Avantages de Clojure (et inconvénients des "autres"):

  • Fonctionne sur la JVM.

    • La JVM est un environnement de langage très stable et de haute performance qui répond assez bien au rêve de Sun de "Écrire une fois, exécuter [presque] n'importe où". Je peux écrire du code sur mon Macbook Pro, le compiler dans un fichier JAR exécutable, puis l'exécuter sur Linux et Microsoft Windows avec peu de tests supplémentaires.

    • La JVM (Hotspot et autres) prend en charge la collecte de déchets de haute qualité et la compilation et l'optimisation juste à temps très performantes. Il y a quelques années à peine, j'écrivais tout ce qui devait tourner vite en C, maintenant je n'hésite plus à le faire en Java.

    • Modèle standard, simple et multithreading. Common LISP a-t-il un package multithreading standard?

    • Brise la monotonie de toutes ces parenthèses avec [], {}, et #{}, bien que les experts communs de LISP me diront probablement qu'avec les macros de lecture, vous pouvez les ajouter à CL.

Inconvénients de Clojure :

  • Fonctionne sur la JVM.
    • Pas de récursivité ou de continuation de queue. Le LISP commun prend-il en charge les continuations? Je pense que le programme nécessite un soutien pour les deux.

Avantages des autres (LISP commun, en particulier) (et inconvénients de Clojure):

  • Macros de lecteur définissables par l'utilisateur.

  • D'autres avantages?

Pensées? D'autres différences?

87
Ralph

Ma liste personnelle de raisons de préférer Clojure à d'autres Lisps (p.s. Je pense toujours que tous les Lisps sont excellents!):

  • Fonctionne sur la JVM - obtient ainsi un accès automatique à l'ingénierie fantastique dans la JVM elle-même (algorithmes avancés de récupération de place, optimisation HotSpot JIT, etc.)

  • Très bon Java interopérabilité - fournit la compatibilité avec la vaste gamme de bibliothèques de l'écosystème de langage Java/JVM. J'ai utilisé Clojure comme langage "glue" pour connecter différents Java bibliothèques avec un bon effet. Comme je développe également beaucoup de code Java, il est utile pour moi que Clojure s'intègre bien avec Java outillage (par exemple, je utiliser Maven, Eclipse avec le plugin Counterclockwise pour mon développement Clojure)

  • Belle syntaxe pour les vecteurs [1 2 3], Plans {:bob 10, :jane 15} et définit #{"a" "b" "c"} - Je considère ces outils assez essentiels pour une programmation moderne (en plus des listes bien sûr!)

  • Personnellement, j'aime l'utilisation de crochets pour les formulaires de reliure: par ex. (defn foo [a b] (+ a b)) - Je pense que cela rend le code un peu plus clair à lire.

  • Accent sur la programmation paresseuse et fonctionnelle avec des structures de données persistantes et immuables - en particulier, toute la bibliothèque Clojure principale est conçue pour prendre en charge cela par défaut

  • Excellente implémentation STM pour la concurrence multicœur. Je crois que Clojure a la meilleure histoire de concurrence de toutes les langues pour le moment (voir ceci vidéo pour plus d'élaboration par Rich Hickey lui-même )

  • C'est un LISP-1 (comme Scheme), que je préfère personnellement (je pense que dans un langage fonctionnel, il est logique de conserver les fonctions et les données dans le même espace de noms)

47
mikera

Une différence importante entre Clojure et Common LISP est que Clojure est plus normatif sur la programmation fonctionnelle. La philosophie, les idiomes de Clojure et, dans une certaine mesure, le langage/les bibliothèques encouragent et insistent parfois pour que vous programmiez de manière fonctionnelle (pas d'effets secondaires, pas d'état mutable).

LISP commun prend certainement en charge la programmation fonctionnelle, mais il permet également un état mutable et une programmation impérative.

Bien sûr, la programmation fonctionnelle présente un certain nombre d'avantages, dans le domaine de la concurrence et autrement. Mais toutes choses étant égales par ailleurs, il est également bon d'avoir le choix de l'approche que vous souhaitez utiliser pour chaque situation. Clojure n'interdit pas complètement la programmation impérative, mais il est moins accommodant de ce style que Common LISP.

24
Charlie Flowers

Gardez à l'esprit que Clojure est un langage et une implémentation (généralement sur la JVM). LISP commun est un langage avec plus de dix implémentations différentes. Nous avons donc un décalage de catégorie ici. Vous pouvez par exemple comparer Clojure avec SBCL.

Généralement:

  • une version de Common LISP s'exécute sur la JVM: ABCL

  • la plupart des autres implémentations LISP communes ne le font pas

  • la plupart des implémentations CL ont des capacités multitâches, une bibliothèque fournit une interface commune

  • LISP commun a une syntaxe pour les tableaux. La syntaxe pour d'autres types de données peut être écrite par l'utilisateur et est fournie par diverses bibliothèques.

  • LISP commun ne prend en charge ni l'optimisation des appels de queue ni les continuations. Les implémentations fournissent le TCO et les bibliothèques fournissent une certaine forme de continuations.

22
Rainer Joswig

Voici une bonne vidéo avec un comparaison de Scheme (Racket principalement) et Clojure .

Pour être honnête, Racket a également du sucre de syntaxe (des trucs de lecture supplémentaires) pour les types de données (#hash, #, crochets, etc.)

De plus, la seule façon pour Clojure de faire un bon appel final est d'utiliser recur, c'est l'inconvénient de la compilation sur JVM.

Notez que recur est la seule construction de boucle non consommatrice de pile dans Clojure. Il n'y a pas d'optimisation des appels de queue et l'utilisation d'auto-appels pour boucler des bornes inconnues est déconseillée. recur est fonctionnel et son utilisation en queue est vérifiée par le compilateur. ( formulaires spéciaux ).

10
Daniil