Lisp a-t-il encore une fonction spéciale qui N'A PAS été adoptée par d'autres langages de programmation?

35

Lisp a-t-il encore une fonction spéciale qui N'A PAS été adoptée par d'autres langages de programmation?

Par Lisp, j'entends tous les langages de programmation Lisp dans leur ensemble. On m'a dit à quel point Lisp est incroyable et je sais que de nombreuses langues ont été inspirées par Lisp. Mais Lisp a-t-il toujours une fonctionnalité de design exclusive qui ne peut tout simplement pas être réalisée dans une autre langue?

La raison pour laquelle j'ai posé la question est que récemment, étant moi-même un programmeur amateur, j'ai commencé à apprendre Clojure juste pour le plaisir, et le résultat est que j'ai trouvé beaucoup de commentaires et de messages liés à Lisp, ne disant qu'une chose: "Lisp est unique ", mais d’autres langages de programmation modernes ont déjà adopté et volé de nombreuses idées de Lisp, telles que les conditions, la récursivité et la fonction de citoyen de premier plan. Et même la métaprogrammation peut être faite en plusieurs langues.

Ai-je oublié quelque chose et est-ce que "Lisp est toujours différent"?

Ou j'ai de la chance parce que d'autres langues modernes ont volé toutes les bonnes parties à Lisp, de sorte qu'il n'est pas nécessaire de creuser dans le monde Lisp entre parenthèses et que "Lisp était différent".

iceX
la source
3
Partager vos recherches aide tout le monde. Dites-nous ce que vous avez essayé et pourquoi il ne répondait pas à vos besoins. Cela montre que vous avez pris le temps d'essayer de vous aider, que cela nous évite de réitérer des réponses évidentes et, surtout, que cela vous aide à obtenir une réponse plus précise et plus pertinente. Voir aussi Comment demander
Gnat le
3
@gnat Thx pour obtenir des conseils et j'ai mis à jour ma question :)
iceX le
10
Un problème est qu’une fois qu’un langage possède un certain sous-ensemble de fonctionnalités de Lisp (par exemple, les expressions S et les macros), les gens prétendent que c’est un Lisp. Ce qui a bien sûr pour conséquence que (selon ces personnes) aucune langue non lisp ne peut avoir ces caractéristiques.
9
Je suppose qu'il n'y a pas d'autre langue où les parenthèses sont la seule forme de regroupement pour tout :-)
Doc Brown
Lisp en tant que famille n’est peut-être pas si unique, mais beaucoup de dialectes lisp (Racket, CL, Scheme, Clojure) offrent toujours beaucoup de fonctionnalités utiles / uniques.
Daniel Gratzer

Réponses:

28

Ce qui a rendu Lisp différent est une référence canonique pour ce type de question . Les deux caractéristiques clés restantes de Lisp qui ne sont pas largement disponibles, selon cet article au moment de sa rédaction, sont:

8. Une notation pour le code utilisant des arbres de symboles.

9. La langue entière toujours disponible. Il n'y a pas de réelle distinction entre le temps de lecture, le temps de compilation et le temps d'exécution. Vous pouvez compiler ou exécuter du code lors de la lecture, de la lecture ou de l'exécution du code lors de la compilation, ainsi que de la lecture ou de la compilation du code au moment de l'exécution.

Le commentaire aborde chaque point et nomme les langues populaires où cette fonctionnalité est disponible.

8, qui (avec 9) est ce qui rend les macros Lisp possibles, est jusqu’à présent encore unique à Lisp, peut-être parce que (a) il nécessite ces parens, ou quelque chose d’aussi grave, et (b) si vous ajoutez cette augmentation de pouvoir finale , vous ne pouvez plus prétendre avoir inventé une nouvelle langue, mais seulement avoir conçu un nouveau dialecte de Lisp; -)

Notez que cet article a été révisé pour la dernière fois en 2002 et qu'au cours des 11 dernières années, de nombreux nouveaux langages ont été créés, dont certains peuvent incorporer toutes ces fonctionnalités Lisp dans leur conception.

Greg Hewgill
la source
2
Ces fonctionnalités ne sont pas propres à Lisp (et aux variantes dérivées directement), et ce depuis assez longtemps.
Donal Fellows
21
@iceX: La différence entre JavaScript et des langages tels que Lisp, Smalltalk, Self, Newspeak, APL, Factor, Forth, etc. est que, dans JavaScript, les programmes sont "morts". Ce sont des fichiers texte. Vous tuez le programme en cours d'exécution, éditez le fichier texte, puis démarrez une nouvelle copie du programme. Dans ces autres environnements (dits "animés"), vous n'arrêtez jamais le programme en cours d'exécution. Le programme en cours d'exécution est lui-même un ensemble d'objets en mémoire que vous manipulez de la même manière que vous manipulez tout autre objet lorsqu'il est en cours d'exécution . (Remarque: ce n'est pas vrai pour Clojure, mais la plupart des Lisps plus âgés le font de cette façon.)
Jörg W Mittag
2
@ JörgWMittag Wow ... Ainsi, les langages de programmation tels que Clojure, Clojurescript, lispyscript ne sont en fait pas des "vrais lisp" car ils ne peuvent pas changer leur code comme le fait Lisp à l'ancienne, comme le fait Common Lisp. Mais ... s'ils ne peuvent pas changer ... pourquoi la peine d'utiliser le S-expression que je pensais être dans le but de la manipulation de code ... (sentiment que je suis tombée dans un profond trou de lapin foncé)
ICEX
4
@iceX: Beaucoup de langues ont evalou similaire, et beaucoup peuvent faire de la métaprogrammation, par exemple Template Haskell. La chose (sans doute) unique à propos de Lisp est que la représentation des données, du code et du méta-code est la même - pas seulement dans la syntaxe, mais en réalité, c'est la même chose.
tdammers
2
@iceX Eval n'en est qu'une partie, mais pas la totalité. Dans Lisp, vous pouvez exécuter du code au moment de la compilation. Vous pouvez exécuter du code au moment de la lecture. Oui, clojure supporte tout le dynamisme de Lisp, il possède des macros, des macros de lecteur et eval, ainsi que la possibilité de joindre un REPL à un programme en cours d'exécution pour le modifier à la volée.
Stonemetal
15

Il est difficile de répondre à cette question, car il faudrait connaître toutes les langues pour savoir qu'aucune autre fonctionnalité ne dispose d'une fonctionnalité particulière disponible dans Lisp. Ce qui suit est basé sur les langues que j'ai expérimentées.

De mémoire, les conditions sont quelque chose que je n'ai pas vu dans une autre langue. Pensez aux "exceptions", mais si la pile d'appels n'est pas déroulée et si l'appelant peut envoyer une valeur de récupération au site d'exception, sans perturber la pile d'appels entre le gestionnaire et la source de l'exception. Pour être juste, il ne s'agit en réalité que d'une application spéciale des continuations, de sorte que Ruby et Scheme (au moins) peuvent le faire.

Le système macro de Lisp bénéficie de la régularité / homoiconicité, mais Scala envisage de les incorporer en tant que fonctionnalité stable dans la version 2.12 et Template Haskell revendique des fonctionnalités similaires. Je dirais qu'ils seront plus complexes sur le plan syntaxique qu'avec Lisp, mais la génération de code au moment de la compilation existe malgré tout.

En y pensant bien, la construction simple de formulaires n’est qu’un type de macro disponible dans Lisp: je n’ai jamais vu d’équivalent de macros de compilation ou de lecture.

La capacité de certains dialectes (par exemple, SBCL ) à enregistrer une image de processus complète et pouvant être reprise est cool, mais encore une fois, elle n’est pas unique: Smalltalk le fait depuis des décennies.

Beaucoup d'autres langages autorisent l'assignation de déstructuration lors du renvoi de tableaux, mais les méthodes # 'valeurs et #' affectations / valeurs multiples semblent toujours être spécifiques à Common Lisp et Scheme (qui peut également effectuer une déstructuration 'régulière' ). "Wantarray" de Perl permet à une fonction de déterminer si elle est appelée dans un contexte scalaire, list ou vide afin de pouvoir ajuster sa valeur de retour de manière similaire (-ish), mais je n'ai pas vu de "vraies" valeurs de retour multiples en dehors du régime / CL.

En termes de fonctionnalités linguistiques, Lisp ne peut probablement pas faire beaucoup plus que les autres langues (la complétude de Turing étant ce qu'elle est). Ce qu'il est , cependant, est une langue où le code est exprimé en termes de ses propres structures de données, ce qui rend la Big Idea ™ -Que code de données quelque chose qui est relativement facile à travailler.

Danny Woods
la source
3
Les macros Scala sont beaucoup moins puissantes que les macros Lisp, ainsi que les macros TH, les macros hygiéniques Scheme, etc. Un système tout aussi puissant se trouve dans MetaLua et Converge.
SK-logic le
4

Après tant de décennies, je ne pense pas qu'il y ait quelque chose d'exclusif à Lisp. Mais même aujourd'hui, il y a beaucoup de choses intéressantes difficiles à trouver en dehors de Lisps. Quelques choses qui me viennent à l’esprit:

  • Un système objet de haute qualité avec des méta-protocoles sophistiqués (CLOS) n'est pas populaire à distance.
  • des méthodes multiples apparaissent de temps en temps quelque part, mais la plupart des gens n'en ont jamais entendu parler.
  • Comme d'autres l'ont fait remarquer, le système de conditions est assez sophistiqué par rapport aux mécanismes de traitement des exceptions populaires.
  • Une représentation compacte de la sémantique du langage (eval), une approche responsabilisante pour définir son langage et le rendre disponible pour des adaptations profondes simples (voir SICP ) - les fonctions "eval" des langages populaires actuels ne partagent tout simplement pas les mêmes propriétés.

Enfin, il y a beaucoup plus à apprendre de Lisp qui ne concerne pas la langue elle-même mais qui est devenue une partie de l'histoire de Lisp et qui s'est perdue dans le temps. Par exemple, Interlisp, Symbolics Genera, etc ... si vous ne mettez jamais la main sur Genera, consultez ce fil de discussion comp.lang.lisp où Kent Pitman décrit comment "Emacs n’est qu’une ombre pâle des Zmacs de Genera" - qui a été activé par ayant un système Lisp puissant dont Zmacs faisait partie, qui fonctionnait sur une machine Lisp.

Thiago Silva
la source
Je n'ai jamais vu une bonne explication des méthodes multiples qui les distinguent des méthodes surchargées , une caractéristique standard de presque tous les langages impératifs modernes, à l'exception du fait que la répartition multiméthodes est résolue de manière dynamique à l'exécution et est donc beaucoup plus lente que l'utilisation de méthodes surchargées. sont résolus au moment de la compilation.
Mason Wheeler
Ils ont des distinctions importantes. Si vous avez des difficultés à trouver des ressources à ce sujet, vous pouvez toujours créer une nouvelle question ici.
Thiago Silva
Julia a plusieurs méthodes, et le polymorphisme paramétrique de Haskell ressemble à plusieurs méthodes. Il existe des moyens de simuler des méthodes multiples dans de nombreuses langues. Le système de conditions est quelque chose que je souhaite particulièrement (éditer et continuer, même si je l’ai vu pour les débogueurs C #).
aoeu256
4

Ce n'est pas nécessairement une caractéristique unique . C’est l’apparence et la convivialité de certains ensembles de fonctionnalités.

JavaScript ou Java ont beaucoup de fonctionnalités de Lisp (machine virtuelle, compilateur / évaluateur, garbage collection, etc.). Mais JavaScript, par exemple, manque de la partie programmation symbolique, des capacités mathématiques (en interne, il n’a que des flottants), de la gestion des erreurs, etc.

De nombreux systèmes Common Lisp sont optimisés pour une voie de développement où l'on étend de nouveaux logiciels de manière incrémentielle, en développant le langage Lisp dans diverses dimensions en utilisant diverses techniques de méta-programmation - sans redémarrer le logiciel pendant longtemps. Il doit donc être flexible et extensible, mais en même temps robuste. Changer la langue (les macros sont essentiellement un moyen pour l’utilisateur d’étendre le compilateur) sans faire planter le programme.

Maintenant, quelque chose comme JavaScript est également utilisé pour étendre un programme, généralement un navigateur Web. Mais la plupart du temps, on ne fait pas beaucoup de méta-programmation en JavaScript - à part du piratage POO .

Exemple:

On peut mettre en oeuvre un logiciel général avancé de mathématiques pour le domaine de la calcul formel de deux manières: écrire le moteur en C avec un langage spécialisé au dessus (comme Mathematica ) ou dans un dialecte Lisp plus avancé. Macsyma / Maxima en Common Lisp, Réduire en Standard Lisp, Axiom en Common Lisp.

(Il y a aussi un ou plusieurs écrits en Python.)

Il n'y a pas beaucoup de systèmes qui offrent l'ensemble des fonctionnalités de quelque chose comme Axiom , qui s'exécute sur Common Lisp.

Ce qui a rendu Lisp attractif pour ce type d’applications, c’est un mélange de fonctionnalités: mathématiques de base avancées (bignums, ratios, ...), calcul symbolique, compilateur interactif, etc. Il est tout à fait possible d’obtenir ces éléments en les implémentant dans niveau de langue. De cette façon, on aura implémenté 50% ou plus d’un système Lisp typique.

Rainer Joswig
la source
2

Pas autant que je sache. Forth est facilement aussi dynamique que Lisp, peut-être davantage car le code dynamique dans Forth ressemble à du code Forth standard, tandis que les macros Lisp ont tendance à utiliser des fonctionnalités différentes de celles du code Lisp standard (dans Clojure au moins, je n'ai jamais utilisé de citation de syntaxe en dehors d'une macro) et Par conséquent, leur apparence est très différente du code Lisp habituel. Pour illustrer le dynamisme de Forth, voici un moyen d'implémenter des commentaires dans Forth :

: (   41 word drop ; immediate
( That was the definition for the comment word. )
( Now we can add comments to what we are doing! )
pierre précieuse
la source
1
Aussi amusant que Forth semble être, je l'ai toujours trouvé désespérément opaque et gênant, peut-être parce qu'il est basé sur une pile et que tout est inversé.
Robert Harvey
2
Par curiosité, qu'entendez-vous par «séparé de la partie principale de la langue»? Les macros dans Lisp ont un accès complet à toutes les fonctions définies au moment de la définition de la macro. Chacune de ces fonctions peut être utilisée pour créer le formulaire que la macro développe. Cela pourrait impliquer des informations extraites d'une base de données et / ou d'un serveur. Votre exemple de commentaire pourrait être défini comme suit: (defmacro comment (& rest body)), n’est-ce pas?
Danny Woods
1
@ DannyWoods Je veux dire que les macros ne ressemblent pas à du code standard. Au moins, vous pouvez distinguer le code de la macro du code normal, car il utilise énormément les guillemets syntaxiques, les épissures sans guillemets, etc., ce qui est inhabituel dans le code normal. Cet exemple de code que j'ai donné ressemble à du code normal jusqu'à ce que vous voyiez l'immédiat. La relecture de ma réponse est juste mal exprimée.
Stonemetal
1
@stonemetal Pas de soucis, mais il est intéressant de noter qu'il n'y a rien de macro-spécifique concernant la citation de syntaxe, que ce soit en Common Lisp ou en Clojure. Il est parfois pratique d’avoir des expressions à l’arrière dans les définitions de fonctions habituelles, et les corps de macros peuvent être construits manuellement avec des listes simples (bien que vous n’ayez à le faire qu’une ou deux fois pour décider que la syntaxe est une bonne chose!)
Danny Woods
1
Pour être juste, la même chose peut être faite en Lisp, en enregistrant une macro de lecteur personnalisée.
fjarri
2

Lisp a de nombreux dialectes et chacun d’eux a son propre ensemble de fonctionnalités. Ma fonctionnalité préférée qui n’a probablement pas été adoptée par une autre langue est la "pile de spaghettis" d’ Interlisp .

La pile de spaghettis est comme une fermeture, mais sur des stéroïdes. Il enregistre non seulement la fonction actuelle, mais tout le contexte jusqu'au sommet de la pile. Quelque chose qui ressemble à une co-routine , sauf que vous pouvez les créer de manière arbitraire, ce qui entraîne une hiérarchie des contextes de pile.

Ddyer
la source
Je ne savais pas ça, allez vérifier, merci pour votre réponse :)
iceX
7
Est-ce la même chose que les continuations de Scheme?
Nicola Musatti
1
@NicolaMusatti, une "pile de spaghettis" est une stratégie d'implémentation commune pour les continuations de type Scheme (pouvant être appelée après le retour de la fonction qui les a créées).
Alex D