Exemple pratique de la flexibilité du Lisp? [fermé]

Quelqu'un essaie de me vendre le Lisp, comme un langage super puissant qui peut tout faire, et puis un peu.

y a-t-il un exemple de code pratique de la puissance du Lisp?

(de préférence avec une logique équivalente codée dans une langue normale.)

67
demandé sur Peter Mortensen 2008-09-20 02:10:32

18 réponses

j'aime les macros.

voici le code pour empiler les attributs pour les gens de LDAP. Il se trouve que j'ai ce code et je l'ai trouvé utile à d'autres.

certaines personnes sont confuses au sujet d'une pénalité de temps d'exécution supposée de macros, donc j'ai ajouté une tentative de clarifier les choses à la fin.

Au Début, Il Y Avait Un Dédoublement

(defun ldap-users ()
  (let ((people (make-hash-table :test 'equal)))
    (ldap:dosearch (ent (ldap:search *ldap* "(&(telephonenumber=*) (cn=*))"))
                   (let ((mail  (car (ldap:attr-value ent 'mail)))
                         (uid   (car (ldap:attr-value ent 'uid)))
                         (name  (car (ldap:attr-value ent 'cn)))
                         (phonenumber (car (ldap:attr-value ent 'telephonenumber))))
                      (setf (gethash uid people)
                            (list mail name phonenumber))))
    people))

Vous pouvez penser à un "laisser liant" comme une variable locale, qui disparaît en dehors de la forme LET. Remarquez la forme des liaisons -- elles sont très similaires, ne différant que par l'attribut de L'entité LDAP et le nom ("variable locale") pour lier la valeur à. Utile, mais un peu verbeux et contient des doublons.

Sur la Quête de la Beauté

maintenant, ne serait-il pas agréable de ne pas avoir toutes ces duplications? D'un commun langage est est AVEC... les macros, qui lient les valeurs basée sur une expression que vous pouvez saisir les valeurs de. Introduisons notre propre macro qui fonctionne comme ça, avec-LDAP-ATTRS, et remplaçons-la dans notre code original.

(defun ldap-users ()
  (let ((people (make-hash-table :test 'equal))) ; equal so strings compare equal!
    (ldap:dosearch (ent (ldap:search *ldap* "(&(telephonenumber=*) (cn=*))"))
                   (with-ldap-attrs (mail uid name phonenumber) ent
                       (setf (gethash uid people)
                             (list mail name phonenumber))))
    people))

vous Avez vu comment un tas de lignes soudainement disparu et a été remplacé par une seule ligne? Comment faire cela? En utilisant des macros, bien sûr -- code qui écrit du code! Macros in Lisp est un animal totalement différent de ceux que vous pouvez trouver en C / C++ grâce à l'utilisation du pré-processeur: ici, vous pouvez lancer real code Lisp (pas le #define fluff dans cpp) qui génère le code Lisp, avant que l'autre code ne soit compilé. Les Macros peuvent utiliser n'importe quel code Lisp réel, c'est-à-dire des fonctions ordinaires. Essentiellement pas de limites.

Se Débarrasser de l'Horrible

donc, voyons comment cela a été fait. Pour remplacer un attribut, nous définissons une fonction.

(defun ldap-attr (entity attr)
  `(,attr (car (ldap:attr-value ,entity ',attr))))

la syntaxe de backquote semble un peu velue, mais ce que il n'est facile. Quand vous appelez LDAP-ATTRS, il va cracher une liste qui contient la valeur de attr (c'est la virgule), suivie de car ("premier élément dans la liste" (paire de cons, en fait), et il y a en fait une fonction appelée first que vous pouvez utiliser, aussi), qui reçoit la première valeur dans la liste retournée par ldap:attr-value . Parce que ce n'est pas le code que nous voulons exécuter lorsque nous compiler le code (obtenir les valeurs d'attribut est ce que nous voulons faire lorsque nous exécutons le programme), nous n'ajoutons pas de virgule avant l'appel.

en tout cas. On avance, vers le reste de la macro.

(defmacro with-ldap-attrs (attrs ent &rest body)
  `(let ,(loop for attr in attrs
         collecting `,(ldap-attr ent attr))
     ,@body)) 

la syntaxe ,@ est de mettre le contenu d'une liste quelque part, au lieu de la liste actuelle.

résultat

vous pouvez facilement vérifier que cela vous donnera la bonne chose. Les Macros sont souvent écrites de cette façon: vous commencez avec code que vous voulez rendre plus simple (la sortie), ce que vous voulez écrire à la place (l'entrée), puis vous commencez à mouler la macro jusqu'à ce que votre entrée donne la sortie correcte. La fonction macroexpand-1 vous indiquera si votre macro est correcte:

(macroexpand-1 '(with-ldap-attrs (mail phonenumber) ent
                  (format t "~a with ~a" mail phonenumber)))

évalue à

(let ((mail (car (trivial-ldap:attr-value ent 'mail)))
      (phonenumber (car (trivial-ldap:attr-value ent 'phonenumber))))
  (format t "~a with ~a" mail phonenumber))

si vous comparez les reliures à LET de la macro développée avec le code au début, vous verrez qu'il est dans la même forme!

Au moment de la compilation vs Runtime: les Macros vs Fonctions

une macro est un code qui est exécuté à compiler-time , avec la torsion ajoutée qu'ils peuvent appeler n'importe quel ordinaire fonction ou macro comme ils le veulent! Ce n'est pas beaucoup plus qu'un filtre fantaisiste, prenant quelques arguments, appliquant quelques transformations et ensuite alimentant le compilateur les s-exps résultants.

en gros, il vous permet d'écrire votre code en verbes qui peuvent être trouvé dans le domaine du problème, au lieu de primitives de bas niveau de la langue! À titre d'exemple stupide, considérons ce qui suit (si when n'était pas déjà intégré)::

(defmacro my-when (test &rest body)
  `(if ,test 
     (progn ,@body)))

if est une primitive intégrée qui ne vous permettra d'exécuter un forme dans les branches, et si vous voulez avoir plus d'un, bien, vous devez utiliser progn ::

;; one form
(if (numberp 1)
  (print "yay, a number"))

;; two forms
(if (numberp 1)
  (progn
    (assert-world-is-sane t)
    (print "phew!"))))

avec notre nouvel ami, my-when , nous pourrions à la fois a) utiliser le verbe le plus approprié si nous n'avons pas une fausse branche, et b) ajouter un opérateur de séquençage implicite, i.e. progn ::

(my-when (numberp 1)
  (assert-world-is-sane t)
  (print "phew!"))

le code compilé ne contiendra jamais my-when , bien que, parce que dans le premier passage, toutes les macros sont étendues de sorte qu'il y a aucune pénalité d'exécution impliqué!

Lisp> (macroexpand-1 '(my-when (numberp 1)
                        (print "yay!")))

(if (numberp 1)
  (progn (print "yay!")))

notez que macroexpand-1 ne fait qu'un niveau d'expansion; c'est possible (la plupart probablement, en fait!) que l'expansion continue plus bas. Cependant, vous finirez par trouver les détails d'implémentation spécifiques au compilateur qui ne sont souvent pas très intéressants. Mais en continuant à étendre le résultat finira soit vous obtenez plus de détails, ou tout simplement votre entrée s-exp retour.

espoir qui clarifie les choses. Macros est un outil puissant, et l'une des fonctionnalités de Lisp que j'aime.

77
répondu Mikael Jansson 2016-07-25 10:51:17

le meilleur exemple que je puisse imaginer est le livre de Paul Graham, On Lisp . Le PDF complet peut être téléchargé à partir du lien que je viens de donner. Vous pouvez également essayer pratique Lisp commune (également entièrement disponible sur le web).

j'ai beaucoup d'exemples peu pratiques. J'ai écrit une fois un programme dans environ 40 lignes de lisp qui pourrait se Parser, traiter sa source comme une liste de lisp, faire une traversée d'arbre de la répertorier et construire une expression qui a évalué à WALDO si l'identifiant waldo existait dans la source ou évaluer à zéro si waldo n'était pas présent. L'expression retournée a été construite en ajoutant des appels à car/cdr à la source originale qui a été analysée. Je n'ai aucune idée de comment le faire dans d'autres langues en 40 lignes de code. Perl peut peut-être le faire en encore moins de lignes.

18
répondu Jason Dagit 2008-09-19 22:16:07

vous pouvez trouver cet article utile: http://www.defmacro.org/ramblings/lisp.html

cela dit, il est très, très difficile de donner des exemples courts et pratiques de la puissance de Lisp parce qu'il brille vraiment seulement dans le code non-trivial. Lorsque votre projet atteint une certaine taille, vous apprécierez les possibilités d'abstraction du Lisp et serez heureux de les avoir utilisées. Des échantillons de code raisonnablement courts, d'un autre côté, ne vous donneront jamais une satisfaction démonstration de ce qui fait la qualité du Lisp parce que les abréviations prédéfinies des autres langues seront plus attrayantes dans les petits exemples que la flexibilité du Lisp dans la gestion des abstractions spécifiques à un domaine.

14
répondu Matthias Benkard 2008-09-19 22:40:03

en fait, un bon exemple pratique est la Macro boucle Lisp.

http://www.ai.sri.com/pkarp/loop.html

la macro de boucle est simplement cela -- une macro de Lisp. Pourtant, il définit essentiellement une mini boucle DSL (Domain Specific Language).

lorsque vous parcourez ce petit tutoriel, vous pouvez voir (même en tant que novice) qu'il est difficile de savoir quelle partie du code fait partie de la macro boucle, et ce qui est "normal" Lisp.

et c'est l'une des composantes clés de L'expressivité du Lisps, que le nouveau code ne peut vraiment pas être distingué du système.

en Java, par exemple, vous ne pouvez pas (d'un coup d'oeil) savoir quelle partie d'un programme vient de la bibliothèque Java standard par rapport à votre propre code, ou même une bibliothèque tierce partie, vous savez quelle partie du code est le langage Java plutôt que simplement la méthode appelle les classes. Certes, c'est TOUT le "langage Java", mais en tant que programmeur, vous êtes limité à exprimer votre application comme une combinaison de classes et de méthodes (et maintenant, des annotations). Alors qu'à Lisp, tout est à portée de main.

Envisager la Commune SQL interface pour connecter Common Lisp pour SQL. Ici, http://clsql.b9.com/manual/loop-tuples.html , ils montrent comment la macro Boucle CL est étendue pour faire de la liaison SQL un"citoyen de première classe".

, Vous pouvez également observer des constructions telles que "[sélectionnez [prénom] [nom] :à partir de [l'employé] :commande-[last-name]]". Ceci fait partie du paquet CL-SQL et est implémenté comme une macro "reader".

voir, dans Lisp, non seulement pouvez-vous faire des macros pour créer de nouvelles constructions, comme des structures de données, des structures de contrôle, etc. Mais vous pouvez même changer la syntaxe de la langue à travers une macro de lecteur. Ici, ils utilisent une macro de lecteur (dans le cas, le symbole ' [ ' ) pour passer à un Le mode SQL pour faire fonctionner SQL comme SQL embarqué, plutôt que comme des chaînes brutes comme dans beaucoup d'autres langues.

en tant que développeurs d'applications, notre tâche est de convertir nos processus et constructions en une forme que le processeur peut comprendre. Cela signifie que nous devons inévitablement " parler bas "au langage informatique, car il" ne nous comprend pas".

Common Lisp est l'un des rares environnements où nous ne pouvons pas seulement construire notre application à partir du haut en bas, mais où nous pouvons élever la langue et l'environnement jusqu'à nous rencontrer à mi-chemin. On peut coder par les deux bouts.

L'esprit, aussi élégant que cela puisse être, ce n'est pas une panacée. Évidemment, il y a d'autres facteurs qui influencent le choix de la langue et de l'environnement. Mais c'est certainement la peine d'apprendre et de jouer avec. Je pense que L'apprentissage du Lisp est un excellent moyen de faire progresser votre programmation, même dans d'autres langues.

13
répondu Will Hartung 2008-09-19 23:40:21

I like Common Lisp Object System (CLOS) and multimethods.

la plupart, sinon la totalité, des langages de programmation orientés objet ont les notions de base de classes et de méthodes. L'extrait suivant de Python définit les classes PeelingTool et légumes (quelque chose de similaire au modèle de visiteur):

class PeelingTool:
    """I'm used to peel things. Mostly fruit, but anything peelable goes."""
    def peel(self, veggie):
        veggie.get_peeled(self)

class Veggie:
    """I'm a defenseless Veggie. I obey the get_peeled protocol
    used by the PeelingTool"""
    def get_peeled(self, tool):
        pass

class FingerTool(PeelingTool):
  ...

class KnifeTool(PeelingTool):
  ...

class Banana(Veggie):
    def get_peeled(self, tool):
        if type(tool) == FingerTool:
            self.hold_and_peel(tool)
        elif type(tool) == KnifeTool:
            self.cut_in_half(tool)

vous mettez la méthode peel dans le PeelingTool et faire accepter la banane il. Mais, il doit appartenir à la classe PeelingTool, donc il ne peut être utilisé que si vous avez une instance de la classe PeelingTool.

the Common Lisp Object System version:

(defclass peeling-tool () ())
(defclass knife-tool (peeling-tool) ())
(defclass finger-tool (peeling-tool) ())

(defclass veggie () ())
(defclass banana (veggie) ())

(defgeneric peel (veggie tool)
  (:documentation "I peel veggies, or actually anything that wants to be peeled"))

;; It might be possible to peel any object using any tool,
;; but I have no idea how. Left as an exercise for the reader
(defmethod peel (veggie tool)
   ...)

;; Bananas are easy to peel with our fingers!
(defmethod peel ((veggie banana) (tool finger-tool))
  (with-hands (left-hand right-hand) *me*
    (hold-object left-hand banana)
    (peel-with-fingers right-hand tool banana)))

;; Slightly different using a knife
(defmethod peel ((veggie banana) (tool knife-tool))
  (with-hands (left-hand right-hand) *me*
    (hold-object left-hand banana)
    (cut-in-half tool banana)))

N'importe quoi peut être écrit dans n'importe quelle langue qui est Turing complet; la différence entre les langues est combien de cerceaux vous devez sauter à travers pour obtenir le résultat équivalent.

Un puissant langues comme Common Lisp , avec des fonctionnalités telles que les macros et le CLOS, vous permet d'obtenir des résultats rapides et faciles sans sauter à travers tant de cerceaux que vous vous contentez d'une solution subpar, ou vous vous trouvez en train de devenir un kangourou.

13
répondu Mikael Jansson 2015-05-06 18:32:00

il y a beaucoup de traits de tueur dans le Lisp, mais les macros en sont un que j'aime particulièrement, parce qu'il n'y a plus vraiment de barrière entre ce que la langue définit et ce que je définis. Par exemple, le Lisp commun n'a pas de construction alors que . Une fois, je l'ai mis dans ma tête, en marchant. C'est simple et propre:

(defmacro while (condition &body body)
  `(if ,condition
       (progn
         ,@body
         (do nil ((not ,condition))
           ,@body))))

et voilà! Vous venez d'étendre le langage Lisp commun avec une nouvelle construction fondamentale. Vous pouvez maintenant, faites:

(let ((foo 5))
  (while (not (zerop (decf foo)))
    (format t "still not zero: ~a~%" foo)))

qui imprimerait:

still not zero: 4
still not zero: 3
still not zero: 2
still not zero: 1

faire cela dans n'importe quelle langue non Lisp est laissé comme un exercice pour le lecteur...

12
répondu Nowhere man 2011-07-19 15:16:32

j'ai trouvé cet article très intéressant:

comparaison du langage de programmation: Lisp vs C++

L'auteur de l'article, Brandon Corfman, écrit au sujet d'une étude qui compare des solutions en Java, C++ et Lisp à un problème de programmation, puis écrit sa propre solution en C++. La solution de référence est les 45 lignes de Lisp de Peter Norvig (écrites en 2 heures).

Corfman trouve que c'est difficile réduire sa solution à moins de 142 lignes de C++/STL. Son analyse du Pourquoi, est une lecture intéressante.

9
répondu Nelson 2008-10-13 12:36:48

ce que j'aime le plus dans les systèmes Lisp (et Smalltalk ), c'est qu'ils se sentent vivants. Vous pouvez facilement sonder et modifier les systèmes Lisp pendant qu'ils fonctionnent.

si cela semble mystérieux, commencez Emacs , et tapez du code Lisp. Tapez C-M-x et voilà! Vous venez de changer Emacs de L'intérieur D'Emacs. Vous pouvez continuer et redéfinir toutes les fonctions Emacs pendant qu'il est en cours d'exécution.

une autre chose est que l'équivalence code = liste fasse la frontière entre le code et les données très mince. Et grâce aux macros, il est très facile d'étendre la langue et de faire rapidement DSLs .

par exemple, il est possible de coder un constructeur HTML de base avec lequel le code est très proche de la sortie HTML produite:

(html
  (head
    (title "The Title"))
  (body
    (h1 "The Headline" :class "headline")
    (p "Some text here" :id "content")))

= >

<html>
  <head>
    <title>The title</title>
  </head>
  <body>
    <h1 class="headline">The Headline</h1>
    <p id="contents">Some text here</p>
  </body>
</html>

dans le code Lisp, l'indentation automatique fait ressembler le code à la sortie, sauf qu'il n'y a pas d'étiquettes fermantes.

8
répondu Sébastien RoccaSerra 2015-05-06 18:33:44

j'aime cet exemple de macro de http://common-lisp.net/cgi-bin/viewcvs.cgi/cl-selenium/?root=cl-selenium il s'agit D'une liaison courante de Lisp au sélénium (un cadre de test de navigateur web), mais au lieu de cartographier chaque méthode, il lit le propre document de définition D'API de sélénium lors de la compilation et génère le code de cartographie à l'aide de macros. Vous pouvez voir l'API générée ici: common-lisp.net/project/cl-selenium/api/selenium-package/index.html

Cela entraîne essentiellement des macros avec des données externes, qui se trouvent être un document XML dans ce cas, mais aurait pu être aussi complexe est la lecture à partir d'une base de données ou d'un réseau. C'est le pouvoir d'avoir tout L'environnement Lisp à votre disposition au moment de la compilation.

7
répondu Lispnik 2009-08-22 09:46:53

Voir comment vous pouvez étendre Common Lisp avec XML template : cl-quasi-citation XML exemple , page du projet ,

(babel:octets-to-string
 (with-output-to-sequence (*html-stream*)
   <div (constantAttribute 42
         someJavaScript `js-inline(print (+ 40 2))
         runtimeAttribute ,(concatenate 'string "&foo" "&bar"))
     <someRandomElement
       <someOther>>>))

 =>

 "<div constantAttribute=\"42\"
       someJavaScript=\"javascript: print((40 + 2))\"
       runtimeAttribute=\"&amp;foo&amp;bar\">
    <someRandomElement>
      <someOther/>
    </someRandomElement>
  </div>"

c'est essentiellement la même chose que le lecteur backtick de Lisp (qui est pour list quasi-citation), mais il fonctionne aussi pour d'autres choses comme XML (installé sur une syntaxe spéciale<>), JavaScript (installé sur `js-inline), etc.

pour en faire clear, ceci est implémenté dans une user library ! Et il compile le XML statique, JavaScript,etc. des parties en UTF-8 des tableaux d'octets littéraux encodés qui sont prêts à être écrits dans le flux réseau. Avec un simple , (virgule) Vous pouvez revenir à lisp et interleave runtime generated data dans les tableaux de octets littéraux.

Ce n'est pas pour les faibles de cœur, mais c'est ce que la bibliothèque compile ci-dessus dans:

(progn
 (write-sequence
  #(60 100 105 118 32 99 111 110 115 116 97 110 116 65 116 116 114 105 98
    117 116 101 61 34 52 50 34 32 115 111 109 101 74 97 118 97 83 99 114
    105 112 116 61 34 106 97 118 97 115 99 114 105 112 116 58 32 112 114
    105 110 116 40 40 52 48 32 43 32 50 41 41 34 32 114 117 110 116 105
    109 101 65 116 116 114 105 98 117 116 101 61 34)
  *html-stream*)
 (write-quasi-quoted-binary
  (let ((*transformation*
          #<quasi-quoted-string-to-quasi-quoted-binary {1006321441}>))
    (transform-quasi-quoted-string-to-quasi-quoted-binary
      (let ((*transformation*
               #<quasi-quoted-xml-to-quasi-quoted-string {1006326E51}>))
        (locally
            (declare (sb-ext:muffle-conditions sb-ext:compiler-note))
         (let ((it (concatenate 'string "runtime calculated: " "&foo" "&bar")))
           (if it
               (transform-quasi-quoted-xml-to-quasi-quoted-string/attribute-value it)
               nil))))))
  *html-stream*)
 (write-sequence
  #(34 62 10 32 32 60 115 111 109 101 82 97 110 100 111 109 69 108 101 109
    101 110 116 62 10 32 32 32 32 60 115 111 109 101 79 116 104 101 114 47
    62 10 32 32 60 47 115 111 109 101 82 97 110 100 111 109 69 108 101 109
    101 110 116 62 10 60 47 100 105 118 62 10)
  *html-stream*)
 +void+)

à titre de référence, les deux grands vecteurs d'octets ci-dessus ressemblent à ceci lorsqu'ils sont convertis en chaîne:

"<div constantAttribute=\"42\"
      someJavaScript=\"javascript: print((40 + 2))\"
      runtimeAttribute=\""

et le second:

"\">
 <someRandomElement>
    <someOther/>
  </someRandomElement>
</div>"

et il se combine bien avec d'autres structures Lisp comme les macros et les fonctions. maintenant, comparez ceci à JSPs ...

7
répondu Attila Lendvai 2015-05-05 21:12:42

j'ai étudié au MIT dans les années 1970. Comme tous les autres étudiants, je pensais que le langage était primordial. Néanmoins, le Lisp était la langue principale. Ce sont des choses pour lesquelles je pense toujours que c'est assez bien:

  • Symbol math. Il est facile et instructif d'écrire la différenciation symbolique d'une expression, et la simplification algébrique. Je les fais toujours, même si je les fais en peu importe.

  • Théorème à prouver. De temps en temps, je fais une piqûre d'IA temporaire, comme essayer de prouver que le tri d'insertion est correct. Pour ça, j'ai besoin de faire des manipulations symboliques, et d'habitude je retombe sur Lisp.

  • Peu spécifiques au domaine des langues. Je sais que Lisp n'est pas vraiment pratique, mais si je veux essayer un peu DSL sans avoir à tout envelopper dans l'analyse, etc. Lisp macros faire facile.

  • petits algorithmes de jeu comme la recherche minimax arbre de jeu peut être fait en comme trois lignes.

  • Voulez essayer lambda calcul ? C'est facile à Lisp.

ce que le Lisp fait surtout pour moi, c'est de l'exercice mental. Ensuite, je peux transmettre cela dans des langues plus pratiques.

en parlant de calcul lambda, ce qui a également commencé dans les années 1970, dans ce même AI millieu, était que OO a commencé à envahir le cerveau de tout le monde, et d'une certaine manière, l'intérêt dans ce que est semble avoir surpassé beaucoup d'intérêt dans ce que bon pour . C'est-à-dire: le travail sur l'apprentissage automatique, le langage naturel, la vision, la résolution de problèmes, tout est allé à l'arrière de la salle pendant que les classes, les messages, les types, le polymorphisme, etc. est allé à l'avant.

7
répondu Mike Dunlavey 2015-05-05 21:47:13

une chose que j'aime est le fait que je peux mettre à jour le code" run-time " sans perdre l'état de l'application. C'est une chose seulement utile dans certains cas, mais quand c'est utile, l'avoir déjà là (ou, pour un coût minime pendant le développement) est beaucoup moins cher que d'avoir à le mettre en œuvre à partir de zéro. D'autant plus que cela coûte "non à presque pas".

6
répondu Vatine 2009-01-14 14:28:01

avez-vous jeté un oeil à cette explication de pourquoi les macros sont puissants et flexibles? Aucun exemple dans d'autres langues cependant, désolé, mais il pourrait vous vendre sur les macros.

5
répondu William Keller 2017-12-08 21:55:39

@Mark,

bien qu'il y ait une part de vérité dans ce que vous dites, je crois que ce n'est pas toujours aussi simple.

les programmeurs et les gens en général ne prennent pas toujours le temps d'évaluer toutes les possibilités et de décider de changer de langue. Souvent Ce sont les gestionnaires de décider, ou les écoles qui enseignent la langue première ... et les programmeurs n'ont jamais le besoin d'investir suffisamment de temps pour arriver à un certain niveau ils peuvent décider que cette langue me fait gagner plus de temps que cette langue.

plus vous devez admettre que les langues qui ont le support de grandes entités commerciales telles que Microsoft ou Sun auront toujours un avantage sur le marché par rapport aux langues sans ce support.

pour répondre à la question originale, Paul Graham tente de donner un exemple ici même si j'admets qu'il n'est pas nécessairement comme pratique comme je voudrais: -)

4
répondu Pat 2008-09-19 22:50:09

une chose spécifique qui m'a impressionné est la capacité d'écrire votre propre extension de programmation orientée objet, si vous n'aimez pas le CLOS inclus.

L'un d'eux est dans Garnet , et un dans de Paul Graham sur Lisp" 151970920 .

il y a aussi un paquet appelé Screamer qui permet la programmation non déterministe (que je n'ai pas évalué).

tout langage qui vous permet de le modifier pour prendre en charge différents paradigmes de programmation doit être flexible.

4
répondu David Thornley 2009-06-01 20:51:23

Vous pourriez trouver ce post par Eric Normand utile. Il décrit comment au fur et à mesure qu'une base de codes se développe, Lisp vous aide en vous permettant de construire le langage jusqu'à votre application. Bien que cela demande souvent un effort supplémentaire au début, cela vous donne un grand avantage plus tard.

2
répondu drewr 2008-09-19 23:13:54

le simple fait qu'il s'agisse d'un langage multi-paradigme le rend très flexible.

2
répondu temp2290 2009-03-01 19:41:52

John Ousterhout a fait cette observation intéressante concernant le Lisp en 1994:

les concepteurs de langue aiment discuter sur pourquoi cette langue ou cette langue doit être meilleur ou pire a priori, mais aucun de ces arguments vraiment importe beaucoup. En fin de compte, toutes les questions linguistiques sont réglées lorsque les utilisateurs votent avec leurs pieds.

si [une langue] rend les gens plus productifs ils utiliseront ensuite c'; quand une autre langue vient le long qui est mieux (ou si elle est ici déjà), alors les gens vont changer de langue. C'est Le La loi, et il est bon. La Loi me dit que le régime (ou tout autre le dialecte) n'est probablement pas la "bonne" langue: trop de gens ont ont voté avec leurs pieds sur les 30 dernières années.

http://www.vanderburg.org/OldPages/Tcl/war/0009.html

-1
répondu Mark Harrison 2008-09-19 22:37:10