Journal Lisp: pourquoi est-ce different ?

Posté par  .
Étiquettes :
0
15
avr.
2005
Bonjour les gens,

Je ne sais pour quelle raison, j'entends de plus en plus parler autour de moi de Lisp. Du coup ca m'a donne envie de m'y mettre et j'ai commence a bouquiner "Common Lisp: a gentle introduction to symbolic computation" [1].
J'avoue que je n'en ai lu que les 150 premieres pages pour l'instant, mais outre l'aspect "tout est une liste" qui est conceptuellement tres elegant, je ne vois toujours pas ce que Lisp permet de faire, que je ne pourrai pas faire avec un autre langage. Il semblerait que Lisp soit tres utilise pour les applications d'intelligence artificielle, mais certains me disent que cela est du a des raisons plus historiques que reellement fonctionnelles.

Un avis eclaire me permettrait de prendre conscience des avantages de ce langage: de la meme maniere que Perl est LE langage de reference pour le developpement aise d'applications manipulant du texte, je voudrais savoir dans quelles circonstances le Lisp est LE langage a utiliser et surtout pourquoi.

merci aux aviseurs eclaires.


[1] http://www-2.cs.cmu.edu/~dst/LispBook/(...)
  • # C'est simple !

    Posté par  . Évalué à 10.

    Lisp ça sert à faire du lisp car c'est un langage fortement récursif !

    Bon ok je sors --------------->[]
    • [^] # Re: C'est simple !

      Posté par  . Évalué à 2.

      Lot of Insipd and Stupid Parenthesis

      je te suis ----> []
    • [^] # Re: C'est simple !

      Posté par  . Évalué à 2.

      Pire que ça, c'est un langage fortement fonctionnel.

      Nous on s'en servais pour faire de l'analyse d'image en cours, et on avais des résultats assez bluffant du point de vue rapidité.

      Sinon, c'est trés facile d'implémenter un algorithme quelconque, donc pour l'IA où l'algorithmique est plus importante que le code en lui-même c'est pas mal.

      Le parcours d'arbre est aussi trés rapide (CAR, branche de gauche, CDR reste de l'arbre) même si ca deviens un peu indigeste avec des trucs comme:

      (car (car (cdr (cdr (car (car l1) (cdr l2))) (car l1))))

      Mais bon, c'est le lisp, et on s'y fais assez vite en fait...
      • [^] # Commentaire supprimé

        Posté par  . Évalué à 4.

        Ce commentaire a été supprimé par l’équipe de modération.

        • [^] # Re: C'est simple !

          Posté par  (Mastodon) . Évalué à 6.

          Ou alors, le lecteur va vérifier qu'il existe bien des raccourcis évitant ces horreurs (caaadr et autres), et que le lisp s'indente très bien automatiquement ;)
          • [^] # Re: C'est simple !

            Posté par  . Évalué à 4.

            Ou alors, le lecteur va vérifier qu'il existe bien des raccourcis évitant ces horreurs (caaadr et autres)

            Eh ben on a fait le tour de la question... lisp offre caaaaadr tandis que python ne propose ni claaaaass, ni impooooort.

            La supériorité de lisp étant démontrée, le lecteur est rassuré :-/
      • [^] # Re: C'est simple !

        Posté par  (site web personnel) . Évalué à 4.


        Le parcours d'arbre est aussi trés rapide (CAR, branche de gauche, CDR reste de l'arbre) même si ca deviens un peu indigeste avec des trucs comme:

        (car (car (cdr (cdr (car (car l1) (cdr l2))) (car l1))))


        Pour écrire ainsi, il faut vraiment vraiment le faire exprès quand même.
        Ça se simplifie aisément en : (caar (cdar l1)) ce qui est très lisible, pas explicite mais lisible. Pour que ce soit explicite, il suffit de taper ça dans une fonction et c'est bon.
  • # Manipuler les listes, donc ...

    Posté par  . Évalué à 2.

    Salut

    Comme tu l'as dit, Perl est très bon pour manipuler le texte car il a toute une batterie d'outils bien pratique.
    En Lisp, tout est liste, donc forcément, il a lui aussi quelque bon outils pour manipuler les listes (cdr, car, cadr ... de mémoire, ca fait un moment que j'en ai plus fait). Ensuite, tous ce qui s'implémente bien sous forme de liste et qui nécessite beaucoup de manipulation de liste pourrait bien tourner en Lisp...

    Bon, malgré tout, j'arrive pas à me convaincre moi même :).
    En Perl, ca se fait très facilement aussi des cdr (prononcer "coudeur" pour ce qui ne connaissent pas :)).

    Doit y'avoir une grosse raison historique en effet. Mais pourquoi les modules Emacs sont en LISP par exemple ? (Stallman adore ca ?) ou des langages comme le DSSSL...
    Personnellement, j'ai du mal avec la syntaxe Lisp, mais bon, c'est purement personnel comme choix
    • [^] # Re: Manipuler les listes, donc ...

      Posté par  . Évalué à 1.

      Mais pourquoi les modules Emacs sont en LISP par exemple ? (Stallman adore ca ?)


      Tu trouveras un élément de réponse à ta question en cherchant où bossait Stallman quand il a fondé le projet GNU.
      • [^] # Re: Manipuler les listes, donc ...

        Posté par  . Évalué à 2.

        Si tu connais la réponse, peux-tu la donner, au lieu de répondre de manière hautaine ?
        Cherche sur google. Regarde dans le man.
        J'ai cherché et je n'ai pas trouvé, est-ce au MIT ?
        Ce genre de réponse apparait trop souvent; Prendre la peine de répondre, taper un commentaire appelant l'autre à faire des recherches plutôt que de donner une réponse simple comme "RMS faisait du LISP au MIT et vu que ça le bottait il a continué", à quoi cela sert-il ?
        • [^] # Re: Manipuler les listes, donc ...

          Posté par  . Évalué à 5.

          Excuse moi, je ne voulais pas du tout répondre de manière hautaine. Comme l'information ne me semblait pas vraiment cruciale pour le débat je voulait juste rapidement te mettre sur la voie.

          Bon avant de refaire la même erreur sache que RMS était en effet au MIT mais dans le labo d'IA, c'est certainement de là que date son interet pour le LISP.

          D'un autre côté je t'assures que ce n'était vraiment pas dur a trouver. http://en.wikipedia.org/wiki/Richard_Stallman(...) (je t'accorde que la version française ne mentionne pas son labo)

          Encore une fois toutes mes excuses si tu t'es sentis insulté, ce n'était pas mon intention.
  • # Réponses

    Posté par  (Mastodon) . Évalué à 10.

    «je ne vois toujours pas ce que Lisp permet de faire, que je ne pourrai pas faire avec un autre langage.»

    Réponse rapide: rien, tous les langages "turing-complets" sont équivalents.

    Réponse longue: c'est un langage fonctionnel élégant, et donc c'est particulièrement agréable à utiliser dans le cas où on manipule des algos plutôt orientés calculs de fonctions, plutôt que pour faire une GUI ;) Par rapport à d'autres langages fonctionnels, j'aime le fait que sa syntaxe contient très peu de règles et d'exceptions, par opposition par exemple à l'ocaml où un débutant doit constament se référer à la documentation pour savoir quel opérateur utiliser et où l'utiliser. En lisp/scheme c'est simple, on a des fonctions et des listes, et on applique une fonction à une liste en ordre préfixe, point.
    • [^] # Re: Réponses

      Posté par  (site web personnel) . Évalué à 2.

      > tous les langages "turing-complets" sont équivalents.

      Un chouette exemple: on peut faire du lisp en c++
      http://www.artima.com/weblogs/viewpost.jsp?thread=92938(...)
    • [^] # Re: Réponses

      Posté par  . Évalué à 2.


      Réponse rapide: rien, tous les langages "turing-complets" sont équivalents.


      Petite correction pour les tatillons.
      Tous les langages de programmations bien fichus sont tuning-complets (cad tous en fait).
      Mais tous les langages ne sont pas tuning-complets. Exemple : j'invente un langage avec une unique instruction qui permet de « rien faire ».

      Conclusion : on choisit un langage de programmation non pas pour ce qu'il permet de faire mais pour tout plein d'autres raisons parmi lesquelles :
      - la facilité / rapidité de conception et de mise en oeuvre,
      - l'absence de bug,
      - l'efficacité du code compilé,
      - la portabilité du code, la pérénnité de l'architecture,
      - faire plaisir à son chef, au client,
      - etc, etc, etc
  • # Church and SAP...

    Posté par  . Évalué à 5.

    Bonjour,

    La thèse Church de énonce que tout ce qui est « calculable » est
    calculable par un SAP (système acceptable de programmation).

    Les machines de Turing forment un SAP, le programmes C aussi et
    plus généralement tout langage de programmation est un SAP.

    Donc, on peut tout faire avec tout.

    La meilleur façon de s'en rendre compte est qu'on peut écrire un
    interprète LISP est C. Donc tout programme LISP peut se coder
    en C (le code de l'interprète + le code LISP dans un tableau).

    L'inverse est vrai aussi.

    Maintenant, il faut se demander la facilité qu'on peut avoir a faire
    certaines choses. Et là, ben c'est plus si clair.

    Je n'aime pas le LISP mais pour ce qui est du paradigme fonctionnel,
    OCAML est très bon des qu'il faut manipuler des structures de
    données un peu évoluées. La récursion plus le filtrage, c'est
    vraiment très puissant.

    Frédéric
  • # Lisp -> ocaml

    Posté par  . Évalué à 6.

    Je dirais que l'intérêt et l'élégance du lisp tiennent à son côté fonctionnel.

    Or il existe un magnifique langage fonctionnel, qui de plus est fortement typé (par inférence, ie: on ne déclare en général pas les types, le système les devine tout seul) et pour lequel on trouve sur le net un livre en français: ocaml (cf http://caml.inria.fr/ )

    Snark
    • [^] # Re: Lisp -> ocaml

      Posté par  (site web personnel) . Évalué à 1.

      Je plussois totalement. Fare du Lisp n'a aucun intérêt du fait que Ocaml permet de faire tout ce que fat lisp, en proposant beaucoup plus de choses : inférence de type poussée, ordre supérieur, etc...

      « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

      • [^] # Re: Lisp -> ocaml

        Posté par  . Évalué à 2.

        et la question est: mais que font donc le lisp et ocaml que les autres ne font pas ?
        Comme explique plus haut "tous les langages turing complets sont equivalents", donc pourquoi un langage comme le lisp semble marquer sa difference de maniere si nette dans la tete de ceux qui en font la promotion
        • [^] # Re: Lisp -> ocaml

          Posté par  . Évalué à 2.

          la facilité de programmation pour certaines applications
        • [^] # Re: Lisp -> ocaml

          Posté par  . Évalué à 4.

          L'assembleur permet aussi de tout faire... simplement c'est moins facile.

          La programmation fonctionnelle permet des solutions très élégantes, et le typage fort d'éviter les erreurs les plus grossières. Ocaml cumule les deux.

          Snark
  • # LISP

    Posté par  (site web personnel) . Évalué à 3.

    Quelques principe simples que j'aime bien :

    - La syntaxe des expression en notation préfixe.

    Ça parait bizarre quand on en a pas l'habitude, mais au final ça simplifie la vie.
    Un exemple :
    (+ 1 2 3 4)
    Notez que l'opérateur plus n'apparaît qu'une fois, contrairenment à la notation traditionnelle 1+2+3+4

    On peut écrire ça (apply + '(1 2 3 4)), c'est à dire "appliquer la fonction + à la liste (1 2 3 4)", puis remplacer + par la fonction de notre choix.

    - La transparence referentielle

    Les fonctions LISP sont sans effets de bord, c'est à dire qu'on peut les voire comme une boite noire prenant une entrée et produisant toujours la même sortie. C'est quelque chose de plutot sympa à avoir quand même :-)
    • [^] # Re: LISP

      Posté par  (site web personnel) . Évalué à 2.

      - La transparence referentielle

      Les fonctions LISP sont sans effets de bord


      Euh, non, c'est faux.
  • # <naïf>Ça sert à faire des jeux</naïf>

    Posté par  (site web personnel) . Évalué à 4.

    Un excellent jeu sortie sous linux entre autre et datant de 1995 : Abuse.
    Ce jeu (type shareware) développé par une startup (Crack Dot Com) qui a fait faillite a été écrit en .... Lisp !

    Ce jeu a été repris en 2001* et carbure au GPL :)

    Bref, Lisp ro><or ;)

    * : http://jeuxlibres.net/showgame/abuse.html(...)
  • # Why Learn Lisp?

    Posté par  . Évalué à 1.

  • # un environnement

    Posté par  . Évalué à 2.

    Common lisp, un peu comme smalltalk, la console, ou emacs (lui même en emacs-lisp), c'est un environnement qui se suffit à lui même. C'est donc un bon milieu pour apprendre à programmer. Une conséquence anecdotique est qu'un programme lisp doit être linké avec tout l'environnement, autour de 15Mo. Les sémantiques du call by name font que potentiellement tout l'envronnement est utilisé.
    Les autres caractéristiques: un lisp s'écrit en 150 lignes (de C: écrit en lisp ça se fait en 2 lignes); les versions incompatibles prolifèrent (conséquence du point précédent).

    Si tu veux faire du lisp, fait du scheme, c'est la même chose en mieux (plus standardisé en particulier).

    Cela dit moi je suis plus un camélien qui ne connait pas les détails, donc si tu veux une recommandation informée je te dirais de te mettre à OCaml, parce que c'est le meilleur langage du monde (et en plus, il est multiparadigme).
    • [^] # Re: un environnement

      Posté par  . Évalué à 2.

      J'ai oublié de citer une source de sagesse: le wiki (http://c2.com/cgi/wiki?CommonLisp(...) ).
      Et pour Scheme aussi, il y a plusieurs versions, donc prends PLT Scheme.
    • [^] # Re: un environnement

      Posté par  . Évalué à 3.

      "utilise ca parce que c'est mieux" :)

      je suis conscient de la difficulte a exprimer concretement les avantages d'un langage , mais, sans vouloir t'offenser, ce genre de reponse ne m'avance pas.

      Je pense maitriser plutot correctement le C, et je n'ai aucun besoin de passer a un langage oriente objet, genre C++ ou Java, parce que je peux faire tout pareil en C. Par contre, pour expliquer pourquoi le C c'est mieux, je dis, par exemple qu'il a l'avantage d'etre plus proche de ce qui se passe reellement dans le processeur et de permettre un controle precis des allocations de memoire; en gros, avec le C, je sais ce qu'il se passe sous le capot de ma machine et je lui explique exactement ce qu'elle doit faire. Maintenant on va me retorquer que les langages objets permettent de penser un programme de maniere differente, ce a quoi je repond que cette maniere de penser peut aussi s'appliquer en utilisant le C.
      On a donc des arguments relatifs au capacite du langage a permettre un certain controle de la machine (haut niveau, bas niveau...), et des arguments relatifs aux facilites a realiser un type particulier de programmation (procedural, objet...)

      Donc pour moi, le C compare au C++ et a Java, permet une grande interaction avec la machine et une grande liberte quand a la facon de penser mon code. Tandis que le C++ s'oriente vers une maniere particuliere de penser son code (normal il a ete fait pour ca), et Java fait sa tambouille tout seul de son cote en ce qui concerne le controle de la machine.

      [chacun des langages precites a ses avantages et ses inconvenients, ainsi qu'une utilisation pour laquelle il est parfaitement adapte, et mon but n'etait pas de reveiller un mechant tout plein de poil; il y a surement des anneries dans le paragraphe precedent, mais c'est juste pour l'exemple... mais si quelqu'un veut corriger, qu'il ne se gene pas, mais n'oubliez pas : ne donnez pas a manger au tout plein de poil !]

      C'est le meme genre de chose que je souhaite avoir pour le Lisp: apparemment, le lisp est tres pratique pour implementer rapidement un algorithme, ou mettre un place une syntaxe specifique a une application donnee (extensibilite tout ca).
      Mantenant concretement, qu'est ce qui me prendra 1 semaine a pondre en C, qui ne me prendrais qu'un jour a faire en lisp ?
      Quel est le contexte de developpement qui fait que le lisp va me coller un sourrire beat sur le visage tellement c'est beau ?

      PS: j'insiste, mais je souhaiterais vraiment comprendre l'engouement qui accompagne ce langage
      • [^] # Re: un environnement

        Posté par  (site web personnel) . Évalué à 3.

        je souhaiterais vraiment comprendre l'engouement qui accompagne ce langage
        Je ne connais pas (encore) Lisp mais il me semble qu'il est assez difficile de comprendre l'intérêt d'un langage sans l'utiliser. Donc plutôt que d'attendre une bonne raison pour t'y mettre, commence maintenant et tu aura ta bonne raison plus tard. Lisp me semble être un langage assez différent des langages classiques que pour qu'il soit intéressant à apprendre sans autre but que pour apprendre quelque chose de nouveau qui permet d'avoir un autre point de vue. Tout ce qu'il faut c'est un peu de littérature sur le sujet pour se lancer mais je ne pense pas que ça soit bien difficile à trouver.

        Personnellement je connaissais le C avant Java et même si je n'aime pas trop Java et que je programmais déjà assez "objet" en C avant, le fait d'apprendre Java m'a permis de comprendre un peu mieux la POO, les exceptions et la reflection par exemple. Je programmerai probablement pas en Java par choix dans l'avenir mais je regrette pas de l'avoir appris.

        D'un autre côté j'ai assez peu d'expérience donc il est possible que ce que je viens de dire ne soit pas très pertinent.

        pertinent adj. Approprié : qui se rapporte exactement à ce dont il est question.

        • [^] # Re: un environnement

          Posté par  . Évalué à 5.

          Donc plutôt que d'attendre une bonne raison pour t'y mettre, commence maintenant et tu aura ta bonne raison plus tard.

          si tu avais lu un peu mieux, tu aurais su que je n'attend pas de m'y mettre; je fais simplement du multithreading: d'un cote je bouquine, de l'autre je demande l'avis d'utilisateurs avertis du langage. Au final j'espere pouvoir acquerir les bases d'un cote, et les perspectives de l'autre; ceci pour eviter de tomber dans un piege classique qui consiste a calquer les pratiques acquises lors de l'apprentissage d'un langage (le C dans mon cas) sur un autre langage (le Lisp)

          Lisp me semble être un langage assez différent des langages classiques que pour qu'il soit intéressant à apprendre sans autre but que pour apprendre quelque chose de nouveau qui permet d'avoir un autre point de vue.

          Si Lisp te semble etre assez different, c'est bien pour toi: ce que je demande c'est en quoi il est assez different, et jusqu'a ce que je lise certains des commentaires de ce journal, je n'en avais pas la moindre idee. Maintenant je commence a avoir quelques pistes. Encore une fois, si je me limitais a faire du C en Lisp, je n'aurai pas la possibilite d'avoir un autre point de vue.
          • [^] # Re: un environnement

            Posté par  . Évalué à 2.

            Je suis assez d'accord et ça me rappelle mon premier cours de Prolog. C'est très très déstabilisant ! Et penser en C pour écrire du Prolog est stupide.
            D'ailleurs, bien qu'ayant pu voir la puissance du Prolog pour certains problèmes, ça me donnait trop de mal de crânes à modifier ma manière de penser... (et je pense que les personnes pensant en Prolog ont la même réaction avec le C)
            • [^] # Re: un environnement

              Posté par  . Évalué à 2.

              je pense que les personnes pensant en Prolog ont la même réaction avec le C

              C'est comme de passer du langue à une autre (du français au chinois, à l'anglais, etc.) : une question d'habitude.
              Sauf que là, on ne choisit pas en fonction de l'interlocuteur mais du problème à traiter.
      • [^] # Re: un environnement

        Posté par  (site web personnel) . Évalué à 5.


        Mantenant concretement, qu'est ce qui me prendra 1 semaine a pondre en C, qui ne me prendrais qu'un jour a faire en lisp ?

        Sans vouloir alimenter le tas de poils, tu viens de répondre sur le pourquoi de l'objet sur le procédural dans certains contextes : en général il apporte une meilleur productivité dans la conception d'applications complexes.
        Et pourquoi utiliser un langage objet avec cette approche comparé à un langage comme le C par exemple : pour la même raison ; ce gain de productivité devient alors plus pertinente dans la conception d'applications complexes.
        Ce que tu mettrais par exemple 1 semaine à pondre en C, tu le mettrais en 1 ou 2 jours avec un langage objet autre que le C++ qui est le 'C' du monde objet (bon ce n'est pas flatteur pour le C vue que C++ a été pensé avec les pieds de Soustroup).

        Quant à Lisp, tout a été dit plus haut : il révéle sa puissance lorsqu'il s'agit d'exprimer de l'algorithmique ; on l'écrit avec naturellement en très peu de lignes de code. CLOS (Common Lisp Object System) est une version objet de Lisp qui, à l'image de Smalltalk, est très puissante dans son expressivité et sa flexibilité.
        En gros, pour simplifier, en C (ou autre langages similaires) tu penses en terme d'instruction. En Lisp/Scheme/ML/... tu penses en terme d'algorithme.
        • [^] # Re: un environnement

          Posté par  . Évalué à 2.

          En gros, pour simplifier, en C (ou autre langages similaires) tu penses en terme d'instruction. En Lisp/Scheme/ML/... tu penses en terme d'algorithme.


          tu ne me croiras peut etre pas, mais cette simplification sous forme d'opposition instruction/algorithme me semble tres parlante. C'est le genre de chose que j'aimerais voir developper par le biais d'exemple.
          Mais comme dit plus haut, le mieux serait que je genere moi-meme ces exemples.
      • [^] # Re: un environnement

        Posté par  (Mastodon) . Évalué à 5.

        Un petit essai pas très révélateur en scheme (vous pouvez tester avec guile):

        1:=> (define square (lambda (x) (* x x)))
        square
        1:=> (define ma_liste '(1 3 42 13 69 10 2))
        ma_liste
        1:=> (map square ma_liste)
        (1 9 1764 169 4761 100 4)
        1:=> (define add_one (lambda (x) (+ x 1)))
        add_one
        1:=> (map (lambda (x) (add_one (square x))) ma_liste)
        (2 10 1765 170 4762 101 5)

        Ici on voir la possibilité de définir une fonction, et de l'appliquer à toute une liste pour obtenir une nouvelle liste contenant les résultats, et ensuite la combinaison de deux fonctions "au vol" pour faire pareil. Ça n'a rien de révolutionnaire, on peut le faire dans tous les langages, mais c'est plus élégant formulé en fonctionnel (Ruby a trouvé un très bon compris entre fonctionnel et imperatif).

        Mais là ou ça devient intéressant, c'est quand on fixe une partie des paramètres d'une fonction, et que ça nous donne une nouvelle fonction (c'est moche en scheme, c'est plus joli en ocaml):
        1:=> (define add (lambda (x) (lambda (y) (+ x y))))
        add
        1:=> ((add 1) 3)
        4
        Ce qui est intéressant c'est que add est une fonction, et quand on écrit (add 1) on obtient une fonction dans laquelle le premier paramètre est fixé à 1. Par conséquent:
        1:=> (map (add 2) ma_liste)
        (3 5 44 15 71 12 4)

        Je vous l'accorde, ce sont des exemples plutôt maladroits parce que les manipulations sont trop simples et peuvent être faites aussi facilement dans un autre langage. L'idée importante c'est qu'en programmation fonctionnelle, une fonction étant une liste comme une autre, on peut la traiter comme un objet "normal". Par conséquent il est très facile de faire des assemblages de fonctions pendant l'exécution du programme, et donc de faire un programme qui "se réécrit tout seul", c'est pour ça que c'est beaucoup utilisé en intelligence artificielle. On peut faire la même chose en C, mais c'est extrêmement laid.

        Ici, au risque d'insister, (map (add 2) ma_liste) est plus intéressant que définir d'abord une fonction toto qui ajoute 2, puis faire (map toto ma_liste). La fonction (add 2) est produite lors de l'évaluation de la ligne, et pourrait être bien plus complexe qu'une addition:
        1:=> (map (lambda (x) ((add x) (square x))) ma_liste)
        (2 12 1806 182 4830 110 6)
        Pour chaque élément x de la liste, on ajoute x au carré de x, et on place le résultat dans une liste.
        • [^] # Re: un environnement

          Posté par  . Évalué à 2.

          L'idée importante c'est qu'en programmation fonctionnelle, une fonction étant une liste comme une autre, on peut la traiter comme un objet "normal". Par conséquent il est très facile de faire des assemblages de fonctions pendant l'exécution du programme, et donc de faire un programme qui "se réécrit tout seul".


          Est ce que je dis une betise si je compare ca aux templates du C++ mais en beaucoup plus souple et elegant puisque definissable n'importe ou dans le code ?
          C'est en effet une caracteristique tres plaisante.
          le coup de la fonction map me plait bien aussi (je n'en suis pas encore arriver la dans mon bouquin)

          merci pour cet exemple instructif
          • [^] # Re: un environnement

            Posté par  (Mastodon) . Évalué à 4.

            «Est ce que je dis une betise si je compare ca aux templates du C++ ?»

            Je connais très mal le C++, mais si je ne me trompe pas c'est associable aux functors que l'on trouve dans la STL (ou aux agents dans eiffel, ou à des pointeurs de fonction en C, ou aux blocs en ruby).

            Les templates servent surtout à abstraire les types de données, alors que là c'est le code qu'on abstrait, comme lorsque l'on définit un callback en C. La différence par rapport au C est dans la facilité de combiner les fonctions pour en former de nouvelles. Ça se fait au vol en lisp alors qu'en C il faudrait définir la fonction explicitement.

            «le coup de la fonction map me plait bien aussi»

            On trouve ce genre de fonctions aussi dans la plupart des langages, dont C++ ou Ruby, donc au pire si tu n'es pas convaincu par le fonctionnel il te reste un espoir ;) Et comme je suis fan de ruby, je ne peux pas m'emêcher:

            [1, 3, 12].map { |i| i*2 }
            => [2, 6, 24]

            [1, 3, 12, 4].find { |i| i > 2 and i < 6 }
            => 3

            > [1, 3, 12, 4].find_all { |i| i > 2 and i < 6 }
            => [3, 4]

            [1, 3, 12, 4].collect { |i| i > 2 and i < 6 }
            => [false, true, false, true]

            Ruby est un langage objet, mais ses blocs viennent directement de la programmation fonctionnelle: ici la méthode map appelle le bloc pour chaque élément, et le |i| nomme "i" le premier paramètre de la fonction. Les fonctions à deux paramètres donnent:

            [ 1, 3, 12, 4 ].sort { |a, b|
            b <=> a
            }
            => [12, 4, 3, 1]
            • [^] # Re: un environnement

              Posté par  (Mastodon) . Évalué à 2.

              (et pour ceux qui suivent et qui ont remarqué que je n'étais pas bien réveillé, en ruby Enumerable.collect et Enumerable.map font exactement la même chose)
            • [^] # Re: un environnement

              Posté par  . Évalué à 3.

              que dire ? .... c'est beau :)
            • [^] # Re: un environnement

              Posté par  (site web personnel) . Évalué à 5.

              J'avoue que pour le map, la possibilité en python d'écrire ce que j'écris quand je fais des maths me plaisent beaucoup :

              >>> square=lambda x:x*x
              >>> ma_liste=[1,2,3,4,5]
              >>> [square(x) for x in ma_liste]
              [1, 4, 9, 16, 25]

              Le find_all :
              >>> [x for x in [1, 3, 12, 4] if x >2 and x < 6]
              [3, 4]

              Mais on peut aussi écrire map, ou filter (pour find_all).

              >>> map(square, ma_liste)
              [1, 4, 9, 16, 25]
              >>> filter(lambda x: x>2 and x<6, [1, 3, 12, 4])
              [3, 4]
      • [^] # Re: un environnement

        Posté par  (Mastodon) . Évalué à 2.

        «pour expliquer pourquoi le C c'est mieux, je dis, par exemple qu'il a l'avantage d'etre plus proche de ce qui se passe reellement dans le processeur et de permettre un controle precis des allocations de memoire»

        Ce n'est pas toujours un avantage, tout dépend des objectifs que l'on se fixe. Un des avantages de la programmation fonctionnelle est de s'éloigner de la machine, et si ce n'est pas un avantage pour toi, tu risque d'être déçu. Par exemple, soyons réalistes, une liste en lisp sera toujours moins efficace qu'un tableau lorsqu'on voudra accéder à un élément en particulier. La plupart des langages fonctionnels font des concessions, et proposent d'utiliser des effets de bord, des structures de données plus proches de la machine, etc. ce qui selon moi leur fait perdre leur facilité d'utilisation.
  • # RPL

    Posté par  (site web personnel) . Évalué à 4.

    les Reverse Polish LISP (HP28) , ou Reverse programming Langage (HP38/48) sont en fait le meme langage, et sont des ahaptations du LISP pour les calculateurs HP.

    Je trouvais vraiment ce langage tres tres confortable, car TOUT est objet: une chaine est un objet, un nombre est un objet, un programme est un objet. Tu peux additionner une chaine et un nombre, un entier avec un reel, concatenner deux programmes ... transformer une matrice en liste ... bref que du bonheur.

    Ce que j ai retenu de ce langage est que tout peut etre objet. Tu fourre tout dans une pile, et basta. Evidement la pile marche a l envers ... Tout peut etre stoque dans une variable (je pecho la touche en cours d appui, je contatene son numero avec la chaine "prog_key_", je charge dans la pile le contenu du fichier dont je viens de construire le nom, et j execute ca a l arrache. Ca peut aussi manipuler des variables globales ou locales ...

    Et cote logique, j ai beaucoup appris. C etait assez lent, mais tres intelligent.

    Mais je ne suis pas la pour faire de la pub a HP; je suis la pour faire de la pub a Linux et au RPL; je passerai outre les emulateurs HP, et je ne citerai que http://www.makalis.fr/~bertrand/rpl2/(...) ... un interpreteur RPL natif ecrit en C, qui se compile sur presque toutes les archi qui ont un compilateur C. Il est compatible avec tous les programmes pour HP28 (mais pas tous les HP48, car de toute facon la 48 n est pas totalement compatible avec la 28 , mais ce n est pas le sujet).

    Apres compilation, tu te retrouve devant un interpreteur RPL, avec toute l intelligence du PRL des caltos, mais toute la puissance d un interpreteur ecrit en C, sans couche d emulation Saturn ni ARM. QUE DU BONHEUR. Y a des sorties GNUPlot, des sauvegardes vers fichiers, manipulations de grands entiers (tout est en 64bits depuis 1 an ).

    Ce qui manque, c est une doc ... car meme avec 6 ans sur HP48, l auteur a du changer un peu l API d acces aux fichiers locaux, et a l affichage ... mais si tu copie colle tes progs a la souris, c est assez foudroyant.

    Le Lisp roxait; HP lui a redonne une jeunesse, Bertrand lui a redonne une troisiemme jeunesse.
  • # Pour un debutant

    Posté par  . Évalué à 4.

    Pour un non informaticien avec une bonne formation scientifique, lisp
    est fantastique. Une heure d'apprentissage et ca roule. Jamais on
    n'hesite sur la ponctuation, la syntaxe. Jamais on ne se prend la tete
    pour savoir dans quel ordre les arguments des fonctions sont
    evalues, c'est toujours dans le meme ordre. Fantastiquement clair.
    Ca illustre parfaitement le dicton qui dit que la methode est
    l'economie de la memoire.
  • # Symboles et mémoire !

    Posté par  . Évalué à 5.

    J'ai parcouru tous les messages et je pense que la plupart des avantages de lisp ont été cités (ou aperçus) :
    - syntaxe simple ;
    - puissance du fonctionnel ;
    - interprété ;
    - réflexif (un programme lisp manipule des listes et est lui-même un liste, donc manipulable).

    Mais personne ne parle de la manipulation des symboles.
    L'un des grands avantages du Lisp c'est qu'il permet de manipuler des symboles.

    En fait, on voit peut-être moins facilement l'intérêt de nos jours avec tous les langages interprétés qui permettent de manipuler très facilement des chaînes de caractères mais un symbole, même si on peut le _réduire_ à une chaîne de caractères, ce n'est pas un simple nom, c'est une entité autonome qui a un sens.
    Pour expliciter un peu dans une analogie pour programmeur, manipuler des symboles au lieu de manipuler des chaînes, c'est comme d'utiliser des constantes nommées : écrire ses calculs en utilisant PI plutôt que 3.1415..., c'est pour que l'intention du programme se retrouve dans le code.
    La différence, c'est qu'un symbole n'a pas forcément de valeur dans le programme ('pi n'a pas besoin d'avoir une valeur pour être manipulé), il suffit qu'il en ait une pour le programmeur.

    P.ex. je peux manipuler des formules mathématiques (les simplifier, les dériver, etc.) sans pour autant donner une valeur (numérique) aux variables et fonctions qu'elle contient. C'est d'ailleurs extrêmement facile en Lisp car les formules sont des arbres, qui sont aussi des listes : il suffit de transformer un peu les éléments (p.ex. (+ 0 x) devient x, (* 0 x) devient 0, ou, en dérivation, (^ x n) devient (* n (^ x (- n 1))), etc.).
    (Remarquez que c'est aussi très facile en Prolog, qui manipule les arbres et les symboles comme personne.)

    Ensuite, on peut donner une valeur aux symboles. On peut même, dans certains dialectes, en donner jusqu'à 9 : 'f peut correspondre à une variable, une fonction, des propriétés, etc.
    C'est-à-dire qu'on peut utiliser le symbole dans différents contextes :

    ? (defun f (x y) (+ x y))
    ? (defvar f 12)
    ? f
    12
    ? (f 1 3)
    4

    À noter qu'en Scheme, symbol-value et symbol-function sont confondues (ce qui peut être pratique mais aussi parfois embêtant).

    Ces valeurs sont aussi accessibles par des fonctions :

    (symbol-function 'f)
    (symbol-value 'f)
    (symbol-name 'f)
    (symbol-plist 'f)

    On remarquera qu'un symbole à un nom (accessible par 'symbol-name) : le symbole n'est pas simplement un nom (comme le doigt n'est pas la lune ni la carte le territoire).

    Un autre gros avantage du Lisp, surtout par rapport aux langages de son âge, c'est son mécanisme de gestion de la mémoire. Je sais, les pros du C diront qu'ils préfèrent faire leur malloc eux-mêmes. Mais lorsque l'on manipule des concepts de haut niveau (imaginez que vous programmez un psychologue logiciel que vous décidez d'appeler, euh, p.ex. « Elisa » ;o), si vous programmez en assembleur ou en C, vous passerez votre temps sur la gestion de la mémoire et des pointeurs.
    On peut aussi dire « la gestion de la mémoire est un domaine très délicat, ce qui est une excellente raison pour ne pas la laisser à un programmeur ».
    • [^] # Re: Symboles et mémoire !

      Posté par  (site web personnel) . Évalué à 2.

      - interprété ;

      ou pas. Il y a plein de compilateurs lisp (et scheme aussi d'ailleurs).
      • [^] # Re: Symboles et mémoire !

        Posté par  . Évalué à 2.

        Oui, et en général, les machines virtuelles lisp (et oui, Java n'a rien inventé) permettent la « précompilation ».

        En tout cas, la caractéristique « interprété » est rarement perdue (sauf en cas de traduction dans un autre langage) : les liaisons sont dynamiques ; elles portent sur les symboles, on peut donc changer la valeur de ces symboles en cours d'exécution.
        • [^] # Re: Symboles et mémoire !

          Posté par  . Évalué à 1.

          Je pense que le mot « interprété » est très mal choisi ! Si tu veux parler de calcul symbolique et de gestion automatique de la mémoire, il est plus correct de parler de virtualisation ou de machine virtuelle.

          À part cela, je suis d'accord avec tous ces arguments. Il manque juste une dernière qualité : le langage Lisp est un langage extensible (cf. le post plus bas) !
          • [^] # Re: Symboles et mémoire !

            Posté par  . Évalué à 2.

            Je parle d'« interprété » car les liaisons sont dynamiques : la suite des fonctions à appliquer est définie _pendant_ l'application. Deux applications qui se suivent, même si elles ont les mêmes arguments, ne feront peut-être pas la même chose. Les chemins ne sont pas « câblés » comme c'est (presque toujours) le cas avec un langage compilé. C'est vrai que c'est fortement lié au calcul symbolique.

            L'extensibilité est une conséquence de la syntaxe simple et du calcul symbolique (entre autres). Et c'est vrai que c'est aussi un avantage certain du Lisp.
  • # Lisp et Fortran

    Posté par  . Évalué à 2.

    Il y a deux types de langages : les langages imperatifs (derives du Fortran) et les langages fonctionnels (derives du lisp).

    Langage imperatif : on ecrit une suite "d'ordres" que l'ordinateur doit executer.

    Langage fonctionnel : on ecrit des fonctions (au sens mathematique du terme, pas une procedure).

    La majorite des langages sont imperatifs, d'autres comme (o)caml, prolog sont fonctionnels. Les machines physiques fonctionnent d'ailleurs de maniere imperative, meme s'il y a eu quelques tests de machines physiques fonctionnelles. Les langages de script recents melangent un peu les deux concepts.

    LISP, c'est un peu comme l'assembleur des langages fonctionnels...
    • [^] # Re: Lisp et Fortran

      Posté par  . Évalué à 1.

      Mouif, un peu réducteur.

      Il y a effectivement des langages impératifs et des langages fonctionnels.
      Par contre, Prolog n'est pas fonctionnel, il est déclaratif : un programme Prolog est un ensemble de règles, celles-ci servent ensuite au moteur de déduction Prolog pour résoudre des requêtes.

      Il y a effectivement eu des tentatives de machines lisp.

      Lisp n'est pas l'assembleur des langages fonctionnels, c'est juste le premier.

      D'ailleurs, j'ai trouvé ce lien il n'y a pas très longtemps, ça peut sans doute vous intéresser : http://homepage.mac.com/aimlin/langages_informatiques.html(...)
      C'est un graphe de « filiation » entre les langages (qui s'inspire de qui).
      (Je n'y ai pas repéré d'erreur flagrante, mais je ne connais pas tous les langages non plus.)
  • # Il suffit d'essayer

    Posté par  . Évalué à 2.

    Pour te faire une bonne idée je te conseille la lecture de Practical Common Lisp, publié par Apress, et dispo en intégralité là:
    http://www.gigamonkeys.com/book/(...)

    Pour développer tu peux utiliser Emacs avec SLIME. J'utilise la version CVS, la dernière release datant un peu. Voir ici:
    http://ww.telent.net/lisp/according_to/slime.html(...)

    Si tu as une Debian à disposition, installe common-lisp-controller, une implémentation de CL (j'utilise SBCL), puis apt-cache search ^cl-

    Tu peux aussi jeter un coup d'oeil sur les différents projets sur http://common-lisp.net/(...)

    L'avantage de (Common) Lisp c'est que la langage est incroyablement flexible (notamment grâce aux macros, tout est un objet, etc.). À tel point que depuis que j'ai commencé à l'utiliser je me surprends à penser "en CL je ferais ça en deux lignes" dès que je code dans un langage comme C/C++/Java. Si je code en Ruby je jure par contre beaucoup moins souvent...

    Dans la sections des inconvénients, on pourra reprocher au standard de ne pas inclure des fonctionnalités qui paraissent maintenant essentielles comme les sockets, mais des bibliothèques tierces les fournissent.

    Pour des exemples d'utilisations de Lisp (Common Lisp surtout):
    http://www.franz.com/success/(...)
    http://alu.cliki.net/Success%20Stories(...)
  • # Lisp est eXtensible

    Posté par  . Évalué à 2.

    Presque tout a été dit sur Lisp ici, et le message de Sylvain Sauvage me semble bien résumer tout cela.
    Mais, pour répondre à la question initiale de Pierre Maziere, je pense qu'il faut revenir un peu sur une qualité qui a été peu expliqué : l'extensibilité du langage Lisp.

    (1) Lisp est un langage vieux. Ces concepts ont été repris dans de nombreux autres langages... OK !

    (2) Lisp est un langage fonctionnel impur (effets de bord possibles). Penser fonctionnel est souvent (pas toujours) plus simple pour concevoir des applications complexes ou pour écrire un algorithme. Le Common Lisp Object System, souvent abrégé en CLOS, apporte aussi le paradigme objet (moi je préfère OCaml, question de goûts)... OK !

    (3) Lisp est un langage réflexif et extensible !!! Ce concept a été repris, évidement, dans plusieurs langages, et a même inspiré un nouveau paradigme de programmation : « la programmation intuitive ».
    Ce dernier point mérite d'être bien expliqué. Il a déjà été abordé précédement :
    Lot of Insipd and Stupid Parenthesis

    La syntaxe des expressions en notation préfixe

    L'un des grands avantages du Lisp c'est qu'il permet de manipuler des symboles... (+ exemples)


    Les mots clefs sont des symboles comme les autres
    La simplicité de la syntaxe de Lisp fait qu'il est très facile et très rapide d'écrire un parser Lisp. Il n'y a pas de règle « spéciale » pour les mots clefs du langage.

    Exemple :

    (if cond list1 list2) équivalent à (maFonction param1 param2 param3).


    Le système de macro du Lisp est très puissant.
    Les macros du C sont un « simple » remplacement de chaînes de caractères effectué par un préprocesseur, donc avant la compilation.
    Une macro Common Lisp est une fonction dont l'objectif n'est pas d'effectuer un calcul à l'exécution, mais de transformer une expression Common Lisp en une autre expression Common Lisp à la compilation ou au chargement. Les macros Lisp sont un remplacement effectué sur l'AST (Arbre de Syntaxe Abstraite) du programme.

    C'est beaucoup plus souple, on peut par exemple examiner le nombre de paramètre pour lever une erreur de compilation ou bien effectuer un remplacement différent en fonction de la valeur d'un paramètre en l'évaluant pendant pendant la compilation et non pendant l'exécution... Je vous laisse imaginer.

    Exemple, définition d'un mot clef while :

    (defmacro while (test &body body)
    `(do ()
    ((not ,test))
    ,@body))


    Conclusion 1 :
    Ces deux qualités associées à celles précités par Sylvain Sauvage permettent de changer facilement la sémantique des mots clefs du langage Lisp, et d'en inventer de nouveau.
    Évidemment, cela plait à la communauté « intelligence artificielle ».

    Conclusion 2 :
    http://en.wikipedia.org/wiki/Domain-specific_language(...)
    Lisp permet de créer un DSL (Domain Specific Langage) !
    ---> simplicité, efficacité

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.