C # Dev - J'ai essayé Lisps, mais je ne comprends pas. [Fermé]


37

Après quelques mois d'apprentissage de Lisp, de CL et d'un peu de Clojure, je ne vois toujours pas de raison impérieuse d'écrire quoi que ce soit à la place de C #.

J'aimerais vraiment avoir des raisons impérieuses ou que quelqu'un indique qu'il me manque quelque chose de vraiment important .

Les points forts de Lisp (d'après mes recherches):

  • Notation compacte et expressive - Plus que C #, oui ... mais il semble que je puisse aussi exprimer ces idées en C #.
  • Prise en charge implicite de la programmation fonctionnelle - C # avec méthodes d'extension LINQ:
    • mapcar = .Select (lambda)
    • mapcan = .Sélectionner (lambda) .Agréger ((a, b) => a.Union (b))
    • voiture / premier = .First ()
    • cdr / rest = .Skip (1) .... etc.
  • Support des fonctions lambda et d'ordre supérieur - C # a ceci, et la syntaxe est sans doute plus simple:
    • "(lambda (x) (corps))" par rapport à "x => (corps)"
    • "# (" avec "%", "% 1", "% 2" est sympa dans Clojure
  • Envoi de méthode séparé des objets - C # a cela par le biais de méthodes d'extension
  • Multimethod dispatch - C # ne l’a pas nativement, mais je pourrais le mettre en oeuvre sous forme d’appel de fonction dans quelques heures
  • Le code, c'est des données (et des macros) - Peut-être que je n'ai pas "obtenu" de macros, mais je n'ai vu aucun exemple où l'idée d'une macro ne puisse pas être mise en œuvre en tant que fonction; ça ne change pas le "langage", mais je ne suis pas sûr que ce soit une force
  • DSLs - Ne peut le faire que par la composition de fonctions ... mais cela fonctionne
  • Programmation "exploratoire" non typée - pour les structures / classes, les propriétés automatiques et "objet" de C # fonctionnent assez bien et vous pouvez facilement passer à une frappe plus puissante au fur et à mesure
  • Fonctionne sur du matériel autre que Windows - Ouais, alors? En dehors du collège, je ne connais qu'une seule personne qui ne gère pas Windows à la maison, ou du moins une machine virtuelle de Windows sur * nix / Mac. (Là encore, c'est peut-être plus important que je ne le pensais et je viens de subir un lavage de cerveau ...)
  • Le REPL pour la conception de bas en haut - Ok, j'avoue que c'est vraiment très sympa, et que ça me manque en C #.

Choses qui me manquent dans Lisp (en raison d'un mélange de C #, .NET, Visual Studio, Resharper):

  • Espaces de noms. Même avec des méthodes statiques, j'aime les lier à une "classe" pour classer leur contexte (Clojure semble avoir cela, CL ne semble pas.)
  • Excellent support de compilation et de conception
    • le système de types me permet de déterminer "l'exactitude" des infrastructures de données que je transmets
    • tout ce qui est mal orthographié est souligné en temps réel; Je n'ai pas besoin d'attendre le runtime pour savoir
    • les améliorations de code (telles que l’utilisation d’une approche de PF au lieu d’une approche impérative) sont automatiquement suggérées
  • Outils de développement d'interface graphique: WinForms et WPF (je sais que Clojure a accès aux bibliothèques d'interface graphique Java, mais elles me sont totalement étrangères.)
  • Outils de débogage de l’interface graphique: points d'arrêt, étape par étape, étape par étape, inspecteurs de valeur (texte, xml, personnalisé), surveillances, débogage par thread, points d'arrêt conditionnels, fenêtre de pile d'appels avec possibilité de passer au code à n'importe quel niveau dans la pile
    • (Pour être juste, mon passage chez Emacs + Slime a semblé fournir une partie de cela, mais je suis partisan de l'approche basée sur l'interface graphique VS)

J'aime beaucoup le battage médiatique qui entoure Lisp et je lui ai donné une chance.

Mais y a-t-il quelque chose que je puisse faire dans Lisp que je ne puisse pas faire aussi bien en C #? C'est peut-être un peu plus bavard en C #, mais j'ai aussi une saisie semi-automatique.

Qu'est-ce que je rate? Pourquoi devrais-je utiliser Clojure / CL?


4
Étant donné que vous programmez déjà dans un style fonctionnel et qu'il semble que vous vous fiez beaucoup à l'infrastructure Windows, je ne vois aucune raison impérieuse de changer de C #. La plupart des gens que je connais utilisent Mac ou Linux, cela dépend donc clairement de la foule avec laquelle vous vous dirigez (j'ai utilisé toutes les versions de Windows depuis la version 3.1, mais je préfère quand même travailler avec des logiciels multiplates-formes et les systèmes * nix en général ... mais alors je ne fais pas de travail d'interface graphique native, tous les serveurs et les éléments de l'interface utilisateur Web)
Sean Corfield

2
Vous pouvez jeter un oeil à The Swine Before Perl . C'est une conversation amusante à écouter et présente un exemple simple de ce pour quoi les macros sont bonnes.
Matthias Benkard

4
"Je n'ai jamais vu un seul exemple où l'idée d'une macro ne puisse pas être mise en œuvre en tant que fonction". J'aimerais voir comment vous écrivez ANDou si vous utilisez ORune fonction. Cela pourrait être fait (étant donné LAMBDAque c'est aussi une macro) mais je ne vois pas de moyen évident de le faire qui ne soit pas totalement nul.

1
"Espaces de noms. Clojure semble avoir cela, CL ne semble pas" - pouvez-vous être plus précis sur ce que vous recherchez? Je n'ai pas vraiment utilisé Clojure, mais ses espaces de noms ressemblent beaucoup aux paquets de CL.

4
Jonathan: CL utilise :(ou ::pour les symboles non exportés) pour nommer les symboles dans les packages, par exemple, votre exemple ici utiliserait http:sessionet chat:session.

Réponses:


23

Les macros vous permettent d’écrire des compilateurs sans quitter le confort de votre langue. Les DSL dans des langages tels que C # constituent généralement un interpréteur d'exécution. Selon votre domaine, cela pourrait poser problème pour des raisons de performances. La vitesse compte , sinon vous coderiez dans un langage interprété et non en C #.

En outre, les macros vous permettent également de prendre en compte les facteurs humains. Quelle est la syntaxe la plus conviviale pour un DSL particulier? Avec C #, vous ne pouvez pas faire grand chose à propos de la syntaxe.

Donc, Lisp vous permet de participer à la conception de langues sans sacrifier votre chemin vers l' efficacité . Et bien que ces questions ne vous intéressent peut-être pas , ils sont extrêmement importants car ils sous-tendent les fondements de tous les langages de programmation utiles orientés vers la production. En C #, cet élément fondamental est exposé au mieux sous une forme très limitée.

L’importance des macros n’est pas perdue dans les autres langues - on pense à Template Haskell, camlp4. Mais là encore, c’est un problème de convivialité - les macros Lisp sont à ce jour probablement l’implémentation la plus conviviale et la plus puissante de la transformation au moment de la compilation.

En résumé, ce que les gens font généralement avec des langages tels que C #, c'est construire des DSIL (langages interprétés spécifiques à un domaine). Lisp vous donne l’opportunité de construire quelque chose de beaucoup plus radical, les DSP (Domain Specific Paradigms). Racket (anciennement PLT-Scheme) est particulièrement inspirant à cet égard: ils utilisent un langage paresseux (Lazy Racket), un langage typé (Typed Racket), Prolog et Datalog, tous imbriqués de manière idiomatique via des macros. Tous ces paradigmes offrent des solutions puissantes à de grandes catégories de problèmes - problèmes qui ne sont pas résolus par une programmation impérative ou même par les paradigmes de la PF.


3
Ce que je trouve intéressant à propos de cet argument est que je n’ai jamais eu la possibilité (ou tout simplement l’ignorée dans mon ignorance) d’implémenter un DSL / DSIL. Pourriez-vous élaborer sur le pouvoir des DSL? (Pour un développeur et un utilisateur.) Cela semble être le gros problème qui me manque vraiment.

15
@ Jonathan Mitchem, vous utilisez déjà de nombreux DSL externes - fichiers de configuration, scripts de construction, configurations ORM, générateurs de code visuel (par exemple, éditeur de Winforms), XAML, générateurs d'analyseurs, etc. Les DSL intégrés sont encore mieux Vous n'avez pas besoin d'un outil de construction distinct pour eux, et ils sont servis dans une seule langue. Et vous devez connaître au moins deux des DSL incorporés - les expressions régulières et le code SQL.
SK-logic

Wow OK. Je n'ai jamais pensé à ceux-ci en tant que DSL. Maintenant, je me suis volontairement écarté de beaucoup de cela, sur la base de "tout ce que je peux faire avec c #, je vais m'en tenir à c #". J'aime coller avec un outil avec un comportement cohérent, personnellement. Mais je comprends la valeur des DSL dans ces exemples.

2
@ Jonathan Mitchem, le problème avec n'importe quel outil est qu'il ne sera pas nécessairement adapté à un objectif donné. Vous devez choisir différents outils pour différentes tâches. Et la puissance de toute méta-langue, y compris Lisp, réside dans le fait que vous n’avez pas à basculer complètement vers un autre outil, car vous pouvez développer vos propres outils spécifiques à un domaine au-dessus de votre langue principale. Je vous suggère de jeter un coup d'œil à Nemerle, il serait plus facile à comprendre pour un développeur C # et ses macros sont presque aussi puissants que Lisp.
SK-logic

3
"J'aime utiliser un seul outil ..." Les DSL correctement conçus dans Lisp ne cachent jamais toute la puissance de Lisp, vous avez donc encore un outil. Ils ajoutent simplement au vocabulaire de manière à rendre le codage d'un domaine particulier plus "naturel", c'est-à-dire avec de meilleures abstractions et une organisation globale.

15

Presque tout ce qui était à l'origine uniquement disponible dans Lisps a heureusement migré vers de nombreuses autres langues modernes. La plus grande exception est la philosophie "le code est la donnée" et les macros.

Le code, c'est des données (et des macros) - Peut-être que je n'ai pas "obtenu" de macros, mais je n'ai vu aucun exemple où l'idée d'une macro ne puisse pas être mise en œuvre en tant que fonction

Oui, les macros sont difficiles à maîtriser. La métaprogrammation en général est difficile à maîtriser. Si vous voyiez une macro pouvant être implémentée en tant que fonction, le programmeur le faisait mal. Les macros ne doivent être utilisées que lorsqu'une fonction ne fonctionne pas.

L'exemple de macro "hello world" consiste à écrire "if" en termes de cond. Si vous êtes vraiment intéressé par le pouvoir des macros, essayez de définir un "my-if" en clojure, en utilisant des fonctions et en observant les ruptures. Je ne veux pas être mystérieux, je n'ai jamais vu personne commencer à comprendre les macros uniquement par une explication, mais ce diaporama est une très bonne intro: http://www.slideshare.net/pcalcado/lisp-macros-in -20 minutes-mettant en vedette-clojure-presentation

J'ai eu de petits projets où j'ai enregistré littéralement des centaines / milliers de lignes de code en utilisant des macros (par rapport à ce qu'il aurait pris en Java). Une grande partie de Clojure est implémentée dans Clojure, ce qui n’est possible que grâce au système macro.


3
Sans toucher à aucun code, je me suis retrouvé dans le scénario d'implémentation d'un "si" sans macros dans ma tête, aussi bien en Clojure qu'en C #. Cela ne peut être fait (ou littéralement). J'avoue que c'est chouette. Mais je manque la connexion de la façon dont cela m'est utile. Que puis-je faire avec les macros (à part écrire "si") que je ne peux pas faire avec une conception fonctionnelle ou OO intelligente? "Comment cela peut-il m'aider?" N'est pas un critère valable pour évaluer une langue, mais pour évaluer si je l'utiliserai. (Je veux vraiment un Lisp qui vaille la peine de passer à Lisp, mais cela ne nous a pas permis de devenir une alternative viable.)

1
Cela va me prendre un peu de temps pour prendre cet exemple. Pour moi, "sauver du code passe-partout" appelle généralement le terme "refactoring", ce qui explique en partie pourquoi les explications ne m'ont pas convaincu. J'ai une solution qui fonctionne dans tous les cas où je l'ai appliquée. Je pense ensuite que la question est de savoir comment identifier les cas dans lesquels vous pouvez utiliser une macro.

1
Je conviens que les macros en valent la peine, mais il n'est pas vrai qu'un my-if les requiert, il peut être écrit comme une fonction d'ordre supérieur (voir un exemple de CL ci-dessous). Vous n'avez vraiment besoin de macros que si vous voulez parcourir le code ou le placer dans un nouveau contexte lexical. (defun my-if (test then &optional else) (cond (test (funcall then)) ('otherwise (funcall else))))

1
En gros, avec une fonction, vous avez le choix d'accepter soit le code cité, que vous pouvez parcourir, mais son contexte lexical lui manque, car vous marchez et l'exécutez dans le contexte lexical de votre fonction. Vous pouvez également accepter les fermetures, qui conservent leur contexte lexical, mais vous pouvez uniquement appeler, ne pas les accompagner ou ajouter quelque chose à leur contexte lexical. Pour faire les deux, vous avez besoin d'une macro, qui peut parcourir et encapsuler le code avant que son développement ne soit placé dans le contexte lexical de l'appel de macro.

7
@ Jonathan Mitchem, la syntaxe LINQ est un bel exemple de ce qui peut être fait avec les macros, mais elle a dû être implémentée dans un noyau de langage, car le langage ne supporte aucune métaprogrammation décente.
SK-logic

14

Je ne suis pas un expert en Common Lisp, mais je connais assez bien C # et Clojure. J'espère que ce point de vue sera utile.

  • Syntaxe simple => power - Lisps correspond à la syntaxe la plus simple possible. Les expressions S sont tout ce dont vous avez besoin. Une fois que vous avez écrit "(appel de fonction arg1 arg2 arg3)", vous l'avez compris. Le reste ne fait que choisir les bons appels de fonction et arguments. Cela semble presque trivialement simple, mais le fait est que cette simplicité est ce qui donne à Lisps tant de force et de flexibilité, et permet en particulier les capacités de méta-programmation pour lesquelles Lisp est célèbre. Par exemple, si je veux qu'une macro appelle plusieurs fonctions différentes sur les mêmes arguments, je fais juste ce qui suit (il ne s'agit pas simplement d'une application de fonction d'exécution, mais d'une macro qui génère du code compilé comme si vous aviez écrit tous les appels de fonction individuels. par la main):
(defmacro print-many [functions args]  
  `(do   
     ~@(map   
        (fn [function] `(println (~function ~@args)))   
        functions)))

(print-many [+ - * /] [10 7 2])  
19  
1  
140  
5/7
  • En raison de la syntaxe incroyablement simple, la philosophie "du code, c'est des données" de Lisp est bien plus puissante que tout ce que vous pouvez faire avec la composition de fonction / modèles / génériques, etc. C'est plus que des DSL, c'est de la génération et de la manipulation de code, au moment de la compilation , en tant que caractéristique fondamentale de la langue. Si vous essayez d’obtenir ce type de capacités dans un langage non homoiconique comme C # ou Java, vous finirez par réinventer Lisp, mal. D'où la fameuse dixième règle de Greenspuns: "Tout programme C ou Fortran suffisamment compliqué contient une implémentation lente ad hoc, spécifiée de manière informelle, encombrée de bogues, de la moitié de Common Lisp". Si vous vous êtes déjà trouvé en train d'inventer un langage de contrôle de flux / gabarit complet dans votre application, vous savez probablement ce que je veux dire ...

  • La concurrence est une force unique de Clojure (même par rapport à d’autres Lisps), mais si vous croyez que l’avenir de la programmation impliquera d’écrire des applications évolutives sur des machines multicœurs, alors vous devriez vraiment vous pencher sur la question - c’est joli révolutionnaire. Clojure STM (logiciel transactionnel de mémoire) fonctionne parce que Clojure embrasse l'immutabilité et les constructions de concurrence simultanées sans verrouillage basées sur une nouvelle séparation de l'identité et de l'état (voir l'excellente vidéo de Rich Hickey sur l'identité et l'état ). Il serait très pénible de greffer ce type de capacité de concurrence sur un environnement langage / exécution dans lequel une proportion importante des API fonctionnent sur des objets mutables.

  • Programmation fonctionnelle - Lisps met l'accent sur la programmation avec des fonctions d'ordre supérieur. Vous avez raison de dire qu'il peut être imité dans des objets OO avec des objets de type fermures / fonction, etc., mais la différence est que l'ensemble du langage et de la bibliothèque standard est conçu pour vous aider à écrire du code de cette manière. Par exemple, les séquences Clojure sont paresseuses et peuvent donc être infiniment longues, contrairement à vos ArrayLists ou vos HashMaps en C # / Java. Cela rend certains algorithmes beaucoup plus faciles à exprimer, par exemple, ce qui suit implémente une liste infinie de nombres de fibonacci:

    (def fibs (lazy-cat '(0 1) (map + fibs (drop 1 fibs))))

  • Dactylographie dynamique - Les lisps ont tendance à se situer à l'extrémité "dynamique" du spectre du langage de programmation fonctionnel (contrairement aux langaages comme Haskell avec une conception très forte et belle des types statiques). Cela présente à la fois des avantages et des inconvénients, mais je dirais que les langages dynamiques ont tendance à favoriser la productivité de la programmation en raison d'une plus grande flexibilité. Ce typage dynamique a un coût de performance d’exécution minime, mais si cela vous dérange, vous pouvez toujours ajouter des indicateurs de type à votre code pour obtenir un typage statique. Fondamentalement, vous obtenez la commodité par défaut et les performances si vous êtes prêt à faire un peu plus de travail pour l'obtenir.

  • Développement interactif - En fait, je pense que vous pouvez obtenir une sorte de REPL pour C # 4.0, mais dans Lisp, il s’agit d’une pratique standard plutôt que d’une nouveauté. Vous n'avez pas du tout besoin de faire un cycle de compilation / construction / test - vous écrivez votre code directement dans l'environnement en cours d'exécution et ne le copiez que plus tard dans vos fichiers source. Cela vous apprend une manière très différente de coder, où vous voyez immédiatement les résultats et affinez votre solution de manière itérative.

Quelques commentaires rapides sur les choses que vous voyez comme "manquantes":

  • Comme vous le dites, Clojure a des espaces de noms. En fait, ce sont des espaces de noms dynamiques: vous pouvez les mettre à jour au moment de l'exécution, ce qui offre des avantages surprenants pour le développement interactif. J'ai eu beaucoup de plaisir à redéfinir des fonctions sous le nez d'un fil d'exécution ou à pirater une structure de données dynamique ....
  • Prise en charge de la compilation / conception - peu utile si vous codez sur un REPL - vous le faites et vous voyez le résultat directement. Cela dit, Clojure commence à obtenir un meilleur support IDE, par exemple le plug-in CounterClockwise pour Eclipse .
  • Développement d'interface graphique - Oui, vous devrez apprendre une nouvelle API, mais ce sera toujours le cas lors du changement de langue. La bonne nouvelle est que les API Java ne sont pas si difficiles et qu'il y a maintenant quelques Clojure intéressantes- wrappers / exemples spécifiques qui semblent assez faciles à utiliser. Voir cette question sur le développement de l'interface graphique Clojure pour quelques exemples intéressants
  • Débogage graphique: cela fonctionne avec le débogueur graphique dans Eclipse en supposant que vous utilisez CounterClockwise ou Enclojure si vous utilisez Netbeans. Cela dit, je n’utilise pas cette fonctionnalité; je trouve que le débogage interactif chez REPL est plus productif.

Personnellement, je trouve les avantages de Clojure / Lisp assez convaincants et je n’envisage pas de revenir à C # / Java (au-delà de ce dont j’ai besoin pour emprunter toutes les bibliothèques utiles!).

Cependant, il a fallu quelques mois pour que je comprenne vraiment tout. Si vous souhaitez véritablement apprendre Lisp / Clojure en tant qu’expérience d’apprentissage enrichissante, rien ne remplace l’immersion en plongée et vous obliger à mettre en œuvre certaines choses .....


1
Merci pour la grande énumération des idées. En fait, j'utilise beaucoup les séquences paresseuses via la construction IEnumerable <> en C # (et je n'ai pas touché à ArrayList depuis 2005), mais je comprends l'idée. Les primitives de concurrence de Clojure sont extrêmement impressionnantes. Il y a quelques années, je faisais de l'informatique en grille en C # (accès simultané sur de nombreuses machines multicœurs), et je crois toujours que c'est l'avenir. La plus grande idée que tout le monde ait eue est probablement la suivante: "il faut vraiment creuser et expérimenter, on ne peut pas vraiment l'expliquer". Donc, je vais continuer à creuser et continuer à vivre.

1
Cool, content d'avoir aidé - et c'est vraiment le bon esprit !!
Mikera

10

C # a beaucoup de fonctionnalités, mais le mélange est différent. Le fait qu'une langue ait une fonctionnalité ne signifie toujours pas qu’elle est facile à utiliser, paradigmatique et bien intégrée au reste de la langue.

Common Lisp a ce mélange:

  • expressions s en tant que syntaxe de données
  • code en tant que données mène à des macros et autres techniques de calcul symbolique
  • langage dynamique permet des modifications d'exécution (liaison tardive, MOP, ...)
  • fortement typé, typé dynamiquement
  • utilisation interactive avec compilateur ou interpréteur incrémental
  • Evaluator en tant que moteur d'exécution principal
  • mémoire gérée avec récupération de place
  • Langage hybride avec un usage intensif de la programmation impérative, fonctionnelle et orientée objet. D'autres paradigmes peuvent être ajoutés (règles, logique, contraintes, ...).

Maintenant, d'autres langages, comme C #, ont ça aussi. Mais souvent pas avec le même accent.

C # a

  • Syntaxe de type C
  • la plupart du temps impératif orienté objet, avec quelques fonctionnalités de PF
  • statiquement tapé
  • principalement par lots avec un compilateur par lots
  • mémoire gérée avec récupération de place

Cela n'aide pas que C # ait par exemple des fonctionnalités de manipulation de code, si elles ne sont pas largement utilisées comme dans Lisp. Dans Lisp, vous ne trouverez pas beaucoup de logiciels qui n'utilisent pas beaucoup les macros de toutes sortes de manières simples et complexes. L'utilisation de la manipulation de code est vraiment une fonctionnalité importante dans Lisp. Émuler certaines utilisations est possible dans de nombreuses langues, mais cela n'en fait pas une fonctionnalité centrale comme dans Lisp. Voir des livres comme 'On Lisp' ou 'Practical Common Lisp' pour des exemples.

Même chose pour le développement interactif. Si vous développez un grand système de CAO, l'essentiel du développement sera interactif depuis l'éditeur et le REPL, directement dans l'application de CAO en cours d'exécution. Vous pouvez émuler une grande partie de cela en C # ou dans d'autres langages, souvent en implémentant un langage d'extension. Pour Lisp, il serait stupide de redémarrer l'application de CAO en développement pour y apporter des modifications. Le système de CAO contiendrait alors également un Lisp amélioré, doté de fonctionnalités de langage (sous forme de macros et de descriptions symboliques) permettant de décrire les objets de CAO et leurs relations (partie, contenu, ...). On peut faire la même chose en C #, mais en Lisp, c'est le style de développement par défaut.

Si vous développez un logiciel complexe en utilisant un processus de développement interactif ou si votre logiciel comporte une partie symbolique importante (méta-programmation, autres paradigmes, calcul formel, composition musicale, planification, ...), alors Lisp peut être fait pour vous.

Si vous travaillez dans l’environnement Windows (ce n’est pas le cas), C # présente un avantage, car il s’agit du principal langage de développement de Microsoft. Microsoft ne prend en charge aucun formulaire Lisp.

Vous écrivez:

  • Espaces de noms. Même avec des méthodes statiques, j'aime les lier à une "classe" pour classer leur contexte (Clojure semble avoir cela, CL ne semble pas.)

Common Lisp n'attache pas d'espaces de nommage aux classes. Les espaces de noms sont fournis par des packages de symboles et sont indépendants des classes. Si vous utilisez CLOS, vous devez réorienter votre approche de la programmation orientée objet.

  • Une excellente compilation et une prise en charge au moment de la conception du système de types me permettent de déterminer la "précision" des infrastructures de données que je transmets. Tout ce qui est mal orthographié est souligné en temps réel; Je n'ai pas à attendre jusqu'à l'exécution pour connaître les améliorations de code (telles que l'utilisation d'une approche de PF au lieu d'une approche impérative) sont automatiquement suggérées

Utilisez le compilateur Lisp. Il vous informe sur les variables inconnues, peut avoir des recommandations de style (selon le compilateur utilisé), donne des astuces d'efficacité, ... Le compilateur est à portée de main.

  • Outils de développement d'interface graphique: WinForms et WPF (je sais que Clojure a accès aux bibliothèques d'interface graphique Java, mais elles me sont totalement étrangères.)

Les systèmes commerciaux Lisps comme LispWorks et Allegro CL offrent des fonctionnalités similaires sous Windows.

  • Outils de débogage de l’interface graphique: points d'arrêt, pas à pas, pas à pas, inspecteurs de valeur (texte, xml, personnalisé), surveillances, débogage par thread, points d'arrêt conditionnels, fenêtre de pile d'appels avec possibilité de passer au code à n'importe quel niveau dans la pile (pour être juste, mon passage chez Emacs + Slime semblait en fournir une partie, mais je suis partisan de l'approche basée sur l'interface graphique VS)

Les Lisp commerciaux comme LispWorks et Allegro CL offrent tout cela sous Windows.


1
Ma critique ne concerne pas vraiment Lisps. Je les trouve assez capables. Je cherche ce qu'un Lisp peut faire / me donner que je ne fais pas déjà. Je comprends tout à fait que la plupart des développeurs C # n'utilisent pas beaucoup des "nouvelles" fonctionnalités du langage. Je pense que le point le plus important est que je le fais, et honnêtement, en dehors de l'interface graphique, j'écris presque dans un style 100% FP. La PF était un saut conceptuel, mais en valait la peine. Cependant, le passage à un Lisp d'où je suis semble offrir peu d'avantages. J'espère trouver une raison pour laquelle je devrais continuer à lui donner une chance.

@ Jonathan Mitchem: C # ne ressemble pas vraiment à un langage de PF, même si le langage a certaines fonctionnalités le supportant et que quelques bibliothèques pourraient les utiliser. Si vous voulez faire de la programmation par PF dans l'éco-système Microsoft, alors F # pourrait vous convenir.

@Rainer Non, cela ne ressemble pas à un langage de PF, mais il peut le faire, de manière assez compacte. Et quand je veux / ai besoin de code impératif, ou de OO, je peux le faire aussi. (légèrement en dehors du sujet: je ne considère pas vraiment F # comme un langage sérieux dans lequel approfondir, je préfère me familiariser avec les monades en Haskell. Mais quand j'étais un développeur C ++ et que C # est sorti, je n'y ai pas pensé. un "vrai" langage non plus [et à l'époque il ne l'était pas, à mon


@ Jonathan Mitchem: pourquoi devrais-je regarder? J'ai écrit que C # supporte certaines fonctionnalités de FP. Cela vient juste d'ajouter à un langage impératif orienté objet et ne le rend pas idiomatique, comme dans Lisp, Scheme par exemple, et surtout pas comparé à SML, F #, Haskell ou à d'autres langages principalement fonctionnels. Mon argument est le suivant: une certaine PF est possible en C #, mais ce n’est pas une fonctionnalité essentielle.

5

Rainier Joswig a dit le meilleur.

Pour moi, la puissance de Lisp ne peut être comprise simplement en regardant une liste de ses fonctionnalités. Pour Lisp, et Common Lisp en particulier, le tout est supérieur à la somme des parties. Il ne s'agit pas seulement des expressions REPL plus s-macros plus de l'envoi multi-méthodes plus des fermetures plus des packages plus des fermetures CLOS plus des redémarrages plus X, Y et Z. C'est de l'ensemble du tout intégré ingénieusement. C'est l'expérience quotidienne qui est très très différente de l'expérience quotidienne des autres langages de programmation.

Lisp a un aspect différent, il est utilisé différemment, l’on aborde la programmation différemment. C'est élégant, complet, grand et sans couture. Ce n'est pas sans ses propres imperfections et peccadilloes. Il existe certainement des comparaisons avec d’autres langues qui pourraient ne pas être précaires. Mais Lisp n’est en aucun cas un langage X plus REPL et des macros, ni un langage Y plus une répartition et un redémarrage à plusieurs méthodes.


3
Le code, c'est des données (et des macros) - Peut-être que je n'ai pas "obtenu" de macros, mais je n'ai vu aucun exemple où l'idée d'une macro ne puisse pas être mise en œuvre en tant que fonction; ça ne change pas le "langage", mais je ne suis pas sûr que ce soit une force

En règle générale, une macro doit être utilisée pour quelque chose qui ne peut être exprimé en tant qu'appel de fonction. Je ne sais pas s’il existe une condition de type commutateur en C # (semblable à ce qui existe en C en tant que switch (form) {case ...}), mais supposons qu’il en existe et qu’elle a presque les mêmes restrictions ( nécessitant un type intégral).

Supposons maintenant que vous souhaitiez quelque chose qui ressemble à cela, mais que vous envoyiez des chaînes. En lisp (en particulier dans Common Lisp et probablement dans d’autres), c’est "juste" une macro et si vous limitez l’utilisateur à avoir des chaînes constantes (probablement pas ardues) pour faire correspondre, vous pouvez calculer (au moment de la compilation) une séquence minimale de tests pour déterminer quel cas correspond (ou utilisez une table de hachage, stockant des fermetures, peut-être).

Bien qu'il soit possible d'exprimer cela sous forme de fonction (chaîne de comparaison, liste des observations et des fermetures à exécuter), il ne ressemblera probablement pas à du "code normal" et c'est là que les macros lisp ont un avantage certain. Vous avez probablement utilisé un bon nombre de macros ou des formulaires spéciaux sont macro-taht comme, comme defun, defmacro, setf, cond, loopet beaucoup d' autres.


2

C'est le meilleur article explicatif que j'ai trouvé qui emmène le lecteur de la surface du plaidoyer Lisp pour montrer certaines des implications plus profondes des concepts utilisés:

http://www.defmacro.org/ramblings/lisp.html

Je me souviens d’avoir lu ailleurs une idée comme celle-ci: d’autres langues ont adopté diverses caractéristiques de Lisp; collecte des ordures, typage dynamique, fonctions anonymes, fermetures pour produire un meilleur C ++ / C / Algol. Cependant, pour obtenir toute la puissance de Lisp, vous avez besoin de toutes ses fonctionnalités essentielles. Vous avez alors un autre dialecte du lisp, une famille de langues distincte qui existe depuis une cinquantaine d'années sous une forme ou une autre.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.