• # Doué?

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

    Je ne connaissais pas le mot et dans a liste de programmes cités je ne connais que le Lisp (un peu).

    Ce que je comprends est que dans un langage homoïconique (je mettrais bien un tréma sur le i) le programme est aussi un type de données.

    Cela signifie que tu peux définir des fonctions d'ordre supérieur qui analysent, produisent, et modifient des procédures qui peuvent être exécutées.

    Tu connais l'équation «Algorithms + Data Structures = Programs» qui sert de titre à un livre (Wirth). Pour écrire un programme il faut donc décider quelle information fait partie de l'algorithme et quelle information fait partie des données.

    Cette décision peut avoir des conséquences très subtiles sur l'organisation d'un programme. Cette décision n'est pas figée: généraliser une procédure signifie souvent reexprimer une partie de l'information «algorithmes» en terme de «types de données».

    Dans un langage homoïconique tu peux facilement:
    — écrire une interpréteur du langage (la partie évaluation est gratuite);
    — déléguer une procédure arbitraire à un autre processus;
    — écrire des outils d'instrumentation (instrumenting, profiling) comme des fonctions du langage et pas des outils externes;
    — écrire des outils de déboguage comme des fonctions du langage et pas des outils externes.

    Pour le dernier, cela signifie que tu peux partiellement automatiser le déboguage du programme. Par exemple ton système en production peut t'envoyer un mail avec un rapport d'erreur très détaillé (partie du code ayant engendré une erreur non traitée et paramères), et ce sans l'aide d'un debogueur!

    • [^] # Re: Doué?

      Posté par  . Évalué à 1.

      C'est un peu le code intelligent. Il s'execute et se comprend.

      Je vais en lire un peu plus sur le LIPS et sur le REBOL (qui va devenir libre), j'ai des livres à porté de main, je verrai bien plus claire à partir de tes dits.

      Merci.

      • [^] # Re: Doué?

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

        Voilà un petit exemple de session scheme (avec guile):

        guile> (define (add a b)(+ a b))
        guile> (procedure? add)
        #t
        guile> (procedure-source add)
        (lambda (a b) (+ a b))
        guile> (eq? 'lambda (procedure-source add))
        #f
        guile> (list? (procedure-source add))
        #t
        guile> (define (procedure-args f)
             (if (procedure? f)
                 (let ((source (procedure-source f)))
                   (if (list? source)
                   (cadr source)
                   '()))
                 '()))
        guile> (procedure-args add)
        (a b)
        
        

        Comme tu vois on peut définir une fonction qui peut ausculter une autre fonction et renvoyer la liste des symboles utilisés comme argument à la fonction.

        Si tu veux t'entraîner tu peux essayer d'effectivement écrire une fonction qui trouve les variables globales utilisées par une fonction — quitte à ne pas supporter toutes les constructions du langage pour simplifier un peu.

        • [^] # Re: Doué?

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

          Je ressors un vieux commentaire, mais ça peut peut-être te donner une idée du lien entre code et données en Lisp (Homoiconicité).

          https://linuxfr.org/news/version-1-0-de-julia#comment-1327245

          • [^] # Re: Doué?

            Posté par  . Évalué à 1. Dernière modification le 04 octobre 2012 à 08:23.

            Intéressant en effet.
            Plus de temps à perdre, je vais lire des cours de LISP.

        • [^] # Re: Doué?

          Posté par  . Évalué à 1.

          Je comprends cette théorie, mais si je m'y mets pas à lire quelque cours, je verrai pas plus claire. Je pense que mon ignorance m'empêche de voir plus loin, malgré vos explications.

          Merci, je vais pas tarder à lire un bon bouquin de LISP, je verrai après pour le Scheme accompagné de GNU Guile.

  • # L'exemple du lisp

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

    Je ne connaissais pas ce terme mais je comprend ce qu'il veut dire, m'en vais donc te l'expliquer (enfin, je vais essayer)

    Prenons l'exemple du lisp (que j'ai appris à l'école et que je n'ai pas touché depuis, il peut y avoir des fautes).

    En lisp tout ce représente par des listes. Un liste pouvant contenir des atomes (entier,…) ou d'autre listes. Ainsi

    (1 2 3 4)
    
    

    représente une liste d'entier et

    ((1 2) (3 4))
    
    

    représente une liste de liste d'entier (jusque là rien de compliqué)

    Là où ça se corse (ça devient intéressant) c'est que le programme
    s’écrit aussi avec des listes (Homoiconicité):

    (+ 1 2 3 4)
    
    

    représente la somme des 4 entiers.

    Ainsi on a : "la principale représentation des programmes est aussi une structure de données d'un type primitif du langage." Tada!!!

    Ça permet d'écrire des programmes qui manipulent leur propre code comme si c'était des données (car c'est des données)

    (defun operate (operators index arg1 arg2)
       ( (nth index operators) arg1 arg2 )
    )
    (operate (list + - / *) 0 3 4) # => (+ 3 4) => 7
    (operate (list + - / *) 2 12 4) # => (/ 12 4) => 3
    (operate (list min max) 1 12 4) # => (max 12 4) => 12
    
    

    en c on serait obligé de passer par des (tableaux de) pointeurs de fonction. C'est jouable pour un cas d'école comme celui-ci, mais tout l’intérêt du lisp est justement de l'utiliser pour des cas qui ne sont pas évident.

    Matthieu Gautier|irc:starmad

    • [^] # Re: L'exemple du lisp

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

      Ça permet d'écrire des programmes qui manipulent leur propre code comme si c'était des données (car c'est des données)

      Oui mais ce n'est pas du tout ce que fait ton exemple, que tu pourrais écrire en C (sans même un paradigme fonctionnel).

      Ce qui illustrerait bien l'homoïcononicité serait de prendre d'écrire des fonctions de ce type:

      (defun find-global-variables (f) …) => liste des variables globales présentes dans f
      
      (defun preserve-global-variables (f) …) => fonction ayant le même effet que f mais l'appel à f ne change pas les varaibles globales
      
      (defun trace-variable (f symbol) …) => fonction ayant le même effet que f mais affiche toutes les modifications de la variable symbol
      
      (defun change-method (f g1 g2)…) => fonction déduite de f en remplaçant tous les appels à g1 par des appels à g2.
      
      
      • [^] # Re: L'exemple du lisp

        Posté par  . Évalué à 1.

        Peux tu écrire du code pour les fonction que tu propose, car cela me parrait impossible.

        (defun find-global-variables (f) …) => liste des variables globales présentes dans f

        Qu'est ce que cela veut il dire? des variables sont glabales ou ne sont pas globales.

        (defun preserve-global-variables (f) …) => fonction ayant le même effet que f mais l'appel à f ne change pas les varaibles globales

        Pour celle la il suffit de copier toutes les varaibles globales, appeler "f" puis réécrire les varaibles globales précédament stockées.

        (defun trace-variable (f symbol) …) => fonction ayant le même effet que f mais affiche toutes les modifications de la variable symbol

        Comment?

        • [^] # Re: L'exemple du lisp

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

          Peux tu écrire du code pour les fonction que tu propose, car cela me parrait impossible.

          J'en suis bien incapable, ne programmant pas en Lisp, cependant si on croit qu'on peut travailler sur une fonction comme si c'était une liste d'instructions on peut utiliser la stratégie suivante:

          On définit find-global-variables-loop (abrégé fgvl) récursive, qui prend en argument une liste L (ensemble) de symboles correspondant aux variables liées et une expression X:

          — Si X est un appel de fonction (f a1 … an) alors il faut renvoyer «les ai qui ne sont pas dans L».

          — Si X est une séquence x1 … xn d'expressions, il faut renvoyer l'union des (fgvl L xi).

          — Si X est une alternative p1 x1 p2 x2 … il faut renvoyer l'union des (fgvl L pi) et des (fgvl L xi), je note pi les prédicats du cond et xi les expressions associées.

          — Si X est un let de a1 v1, a2 v2 … sur x il faut renvoyer l'union des (fgvl L vi) avec (fgvl L' x) où L' est déduit de L en ajoutant les ai.

          Qu'est ce que cela veut il dire? des variables sont glabales ou ne sont pas globales.

          Je voulais dire «référencées» dans f.

          Pour celle la il suffit de copier toutes les varaibles globales, appeler "f" puis réécrire les varaibles globales précédament stockées.

          Oui, en utilisant find-global-variables pour obtenir la liste des variables en question.

          >(defun trace-variable (f symbol) …) => fonction ayant le même effet que f mais affiche toutes les modifications de la variable symbol

          Comment?

          En remplaçant les instructions de type (set a …) par une séquence (set a …) suivie de (output a …) et en changeant le corps des fonctions où a est en argument pour afficher la valeur de a avant le traitement.

          PS: j'ai moinssé par erreur ton commentaire, dans un grand moment d'égarement psychomoteur… j'espère que tu ne m'en voudras pas!

          • [^] # Re: L'exemple du lisp

            Posté par  . Évalué à 1.

            Ouh, j'ai du pain sur la planche, car j'ai pas super bien compris.

          • [^] # Re: L'exemple du lisp

            Posté par  . Évalué à 1.

            Je n'avais pas pensé à modifier le code directement et le réévaluer par la suite.
            Ça semble tout de même dangereux, modifier du code sans le comprendre, car si le code fait des (let [b a] ….) comment tu trouve tes (set a …) ?

    • [^] # Re: L'exemple du lisp

      Posté par  . Évalué à 1.

      Mais c'est énorme ! Une vision pythagoricienne "tout est chiffre".

  • # Lisp

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

    Je vais prendre l'exemple du Lisp que je connais un peu.

    En Lisp, tout est liste.
    La structure de donnée de base est la liste : (a b c d) est une liste de quatre éléments.

    Un programme est aussi une liste. Le premier élément de la liste est une fonction et les suivants sont les arguments. Par exemple, (print '(a b c d)) affiche le contenu de la liste précédente. Le « ' » indique que la liste suivante est une donnée et qu'il ne faut pas tenter de l'interpréter.

    De même, une fonction est une liste :

    (defun taille (l)
      (if (null l)
        0
        (+ 1 (taille (cdr l)))))
    
    

    Calcule la taille d'une liste. Ainsi (taille '(a b c d)) renverra 4.

    • [^] # Re: Lisp

      Posté par  . Évalué à 1.

      Tout est liste, tout est donnée ? C'est bien ça ? Je voulais voir du coté du LISP et du REBOL qui va devenir libre. Je ne sais pas exactement qu'est ce que m'apporteront ces langages, mais je sais que le LISP ou le Scheme avec GNU Guile est très alechant, et de même que REBOL avec sa spécifité réseau.

      Je vais voir d'un peu plus près ces langages, je verrai bien qu'est ce qui differencie des autres langages, et comprendre correctement l'Homoiconicité.

      Merci.

      • [^] # Re: Lisp

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

        Pour Scheme Structure and Interpretation of Computer Programs, 2nd Edition

        http://mitpress.mit.edu/catalog/item/default.asp?ttype=2&tid=3305

        Ce livre est disponible en ligne, et qu'on s'intéresse au Scheme ou non c'est de toutes façons un classique.

        • [^] # Re: Lisp

          Posté par  . Évalué à 1.

          Oh super, ça m'interesse.

      • [^] # Re: Lisp

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

        Un programme est une donnée, c'est ça.

        Rebol est encore vivant ? J'en avait fait pour un projet de fac suite à un Login: ou LinuxMag, mais ça commence à dater.

        • [^] # Re: Lisp

          Posté par  . Évalué à 1.

          Ca va passer en licence open source. Normalement l'auteur a dit GPL2, mais ça pourrait bien etre BSD ou MIT.

    • [^] # Re: Lisp

      Posté par  (site web personnel) . Évalué à 3. Dernière modification le 04 octobre 2012 à 09:36.

      Je vais prendre l'exemple du Lisp que je connais un peu.
      En Lisp, tout est liste.

      Ça commence mal.

      Regarde ce programme lisp :

      1

      Ou celui-ci :

      t

      Ou celui-là :

      '#.-42

      Ou encore :

      '|lol kthx bye|

      Tout ce que l'homoiconicité ("même image") dit, c'est que le code peut être représenté par des données du langage.
      Pour faire simple, si tu as un programme dont le code source est S, alors tu peux peux mettre S dans une variable d'un autre programme du même langage.

      En (Common) Lisp ou en Scheme

      (+ 1 3)

      est un programme, et tu peux écrire

      (let ((x '(+ 1 3))) ...)

      et ça préserve la structure du programme initial.

      alors qu'en C, tu ne peux pas.
      Au mieux, tu fais
      ```
      x = "#include int main(int a, int**b){return 42;}"
      '''
      mais ta chaîne de caractères est une chaîne, pas un programme. Pas possible de l'executer, pas possible de l'analyser sans faire un lexer, un parser…

      • [^] # Re: Lisp

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

        Oui, j'ai pris un raccourci grossier. Mais bon, dès qu'on veut faire des trucs un peu intéressants, les listes pointent le bout de leur nez.

  • # Machine Learning

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

    Je crois que c'est cette propriété qui rend le LISP intéressant en Programmation génétique (machine learning). Cela rend la modification du programme par lui-même plus simple. J'avais vu un exemple simple de ce type, mais impossible de retrouver le lien…

Suivre le flux des commentaires

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