IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Lisp Discussion :

écrire fonction ayant un nombre non fixe a l'avance d'arguments en LispWorks


Sujet :

Lisp

  1. #1
    Futur Membre du Club
    Homme Profil pro
    chercheur en biologie théorique
    Inscrit en
    Avril 2017
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : chercheur en biologie théorique
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2017
    Messages : 6
    Points : 5
    Points
    5
    Par défaut écrire fonction ayant un nombre non fixe a l'avance d'arguments en LispWorks
    Tout d'abord bonjour aux membres du forum ; je suis un tout nouveau venu.

    Je fais la théorie de machines formelles capable de modifier leurs connexions et je programme en Le_Lisp depuis 1980 (sous win98 !!!)
    Recemment j'ai decide de programmer en lisp sur un mac sous OSx et ai telecharge LispWorks personal.

    Voici le problème que je me pose :

    Il existe en Lisp (Le_Lisp et LispWork) des fonctions qui ont un nombre indéterminé d'arguments, exemple

    (+ 2 3 4 5 .... 7) ramene la somme de ces nombres quelque soit le nombre d'arguments de la fonction "+", le nombre de ces nombres.

    Pour écrire des programmes opérant sur des matrices de connexion,
    je voudrais creer une fonction ou logique ayant un nombre quelconque d'arguments, sur l'ensemble (0, 1) et non sur l'ensemble (T, nil) comme c'est le cas avec Le_lisp et LispWorks.
    pour être plus précis appelons cette fonction ou_logique, je voudrais pouvoir évaluer des expressions telles que (ou_logique 0 0 1 0 0 .... 0)
    ou_logique donc admet comme arguments un nombre quelconque de 0 et de 1 et ramène 1 si et seulement si il y a un ou plusieurs "1" figurant parmi ces arguments et 0 dans tous les autres cas, c'est a dire quand tous les arguments sont égaux a "0".

    Quelqu'un peut il m'écrire une defintion de cette fonction en LispWorks

    Je vous remercie.


    JPMoulin

  2. #2
    Membre actif
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Mai 2013
    Messages : 152
    Points : 275
    Points
    275
    Par défaut
    Une telle fonction existe déjà en Common Lisp, c’est logior.

    Mais c’est une vraie fonction. Elle évalue tous ses arguments avant de calculer le résultat. Par contre, or est paresseux : il n’évalue que le nombre des arguments qui suffit pour calculer le résultat. Donc,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CL-USER> (or t (error "erreur"))
    T
    CL-USER> (logior 1 (error "erreur"))
    erreur
       [Condition of type SIMPLE-ERROR]
    C’est pourquoi or est un macro et ne pas une fonction.

    Pour définir une fonction avec un nombre variable des arguments on emploie le keyword &rest. La valeur du symbole suivant dans le corps de la fonction sera la liste des arguments. Par exemple, soit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (defun f (x y &rest zs) ...)
    alor si l’on appelle (f 1 2 3 4 5), la valeur de x sera 1, celle de y sera 2 et celle de z sera (3 4 5). Voilà un exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    (defun write-lines (&rest lines)
      (dolist (line lines)
        (write-line line)))
     
    CL-USER> (write-lines "ligne 1" "ligne 2" "ligne 3")
    ligne 1
    ligne 2
    ligne 3
    On peut utiliser &rest dans des macros aussi.

    Si tu veux un macro paresseux équivalent à logior, le voilà :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    (defun ou-logique% (nombres)
      (cond ((null nombres) 1)
            ((null (rest nombres)) (first nombres))
            (t (let ((premier-argument (gensym)))
                 `(let ((,premier-argument ,(first nombres)))
                    (if (not (zerop ,premier-argument))
                        ,premier-argument
                        ,(ou-logique% (rest nombres))))))))
     
    (defmacro ou-logique (&rest nombres)
      (ou-logique% nombres))
     
    CL-USER> (ou-logique 0 0)
    0
    CL-USER> (ou-logique 0 1 0)
    1
    CL-USER> (ou-logique  1 (error "erreur") 0 0 0)
    1
    Bref, je veux que
    (où a, b et c sont des expressions) équivaille à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    (let ((toto a))
      (if (not (zerop toto))
          toto
          (let ((tata b))
            (if (not (zerop tata))
                tata
                (let ((titi c))
                  (if (not (zerop titi))
                      titi
                      d)))))) (*)
    (l’astérisque ne fait pas partie du code, il est là pour faire des références). De cette façon, si l’un des arguments n’est pas zéro, les arguments suivants ne sont pas évalués. La tâche du macro, c’est de construire la liste (*) à partir des arguments a, b, c et d. Pour faciliter la tâche, j’écris une fonction auxiliaire ou-logique% qui transforme la liste (a b c d) en (*). Il suffit d’employer une récursion très simple, parce que le calcul aura lieu pendent la compilation.

    Pour définir le macro ou-logique, il ne reste qu’appliquer la fonction à la liste des arguments du macro.

    Je peux, peut-être, expliquer plus en détail comment ça marche, mais les macros sont une matière plus avancée.

    PS Il y a plusieures implémentations libres de Common Lisp. Clozure CL + Emacs + Slime doivent marcher sur un mac.

    PPS 1980, c’est sérieux...

  3. #3
    Futur Membre du Club
    Homme Profil pro
    chercheur en biologie théorique
    Inscrit en
    Avril 2017
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : chercheur en biologie théorique
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2017
    Messages : 6
    Points : 5
    Points
    5
    Par défaut remerciements
    Bonjour

    Je te remercie beaucoup du mal que tu t'es donne a répondre. La solution que tu donnes se rapproche beaucoup de cele que que j'ai trouvee hier soir.

    Hier soir, je parcourais "GNU Emacs 24.1 Lisp Reference Manual" je suis tombe sur un exemple similaire a ce que je cherchais et a force de trifouillages, j'ai obtenu ce qui suis et qui répond a la question que je pose dans le primer message :

    ;fonction avec nombre argument non precise et marchant avec des 1 et des 0

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    (defun new_or (a &rest b)
              (setq liste (list a b))
              (setq nliste (append (list (car liste)) (car (cdr liste))))
            ;  (print (list (car liste)))
            ;  (print (car (cdr liste)))
            ;  (print nliste)
              (if (member '1 nliste) 1 0))

    les print avec les points virgules sont des trucs que je mets car j'ai mis longtemps a me debarasser du passage des arguments sous forme de liste ramener par &rest, j'espère que cette explication est claire

    quand je tape

    (new_or 0 0 0 0 .... 0 0 0) cela ramene 0
    (new_or 0 0 1 0 .... 0 0 0) cela ramene 1
    ce qui répond bien a la question.

    Je vois a ta réponse que j'aurais pu virer dans la liste des arguments a et ne garder que &rest. Je me suis complique la vie et ai écrit quelque chose d'assez laid.

    En ce qui concerne les autres langages lisp sur mac, j'ai essaye et j'ai renonce assez vite pour ne pas dire presque immédiatement car on part tout de suite dans toute une série de manipulations informatiques avant d'avoir un truc qui marche effectivement qui pour le non informaticien que je suis paraissent un surcroit de problèmes, c'est pour cela que j'ai adopte LispWorks que j'ai pu utiliser immédiatement.

    Je te remercie beaucoup encore une fois.

    J-P Moulin

  4. #4
    Futur Membre du Club
    Homme Profil pro
    chercheur en biologie théorique
    Inscrit en
    Avril 2017
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : chercheur en biologie théorique
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2017
    Messages : 6
    Points : 5
    Points
    5
    Par défaut remerciements bis
    Re bonjour

    je viens d'évaluer


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    (defun new_or ( &rest b)
              (setq liste b)
              (if (member '1 liste) 1 0))

    j'ai une fonction ou sur l'ensemble {0, 1} qui ramène 1 si j'ai un ou plusieurs 1 parmi les arguments de new_or sinon 0

    Merci

    J-P Moulin

  5. #5
    Membre actif
    Homme Profil pro
    Inscrit en
    Mai 2013
    Messages
    152
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Mai 2013
    Messages : 152
    Points : 275
    Points
    275
    Par défaut
    Bien, si tu ne veux pas qu’une fonction, je te conseille d’utuliser logior. C’est standard, c’est-à-dire, tous le monde la comprend et elle est probablement plus efficace et plus robuste qu’une fonction improvisée. C’est bit or, mais si tous les arguments n’ont qu’un bit chaqu’un, c’est ce qu’il te faut. Donc, la fonction or_new est seulement un exercise.

    J’ai les remarques suivantes.

    1. En Common Lisp, on n’utilise jamais d’underscores, mais plutot des traits d’union: new-or.

    2. Un programme en Common Lisp est composé des S-expressions, c’est-à-dire des atoms et des listes. Chaque expression est évaluée, c’est-à-dire, elle ramène une valeur en effectuant, peut-être, des actions sécondaires (par exemple, l’entrée ou la sortie des données).

    Un nombre, un charactère ou une chaîne littérale sont évalués à eux-mêmes. Ça veut dire que « 1 », par exemple, est une expression, dont la valeur est 1. Ou bien on peut écrire "salut" dans le REPL, et le résultat sera "salut".

    Par contre, un symbole n’est pas par défaut évalué à lui-même. Un symbole est évalué à une valeur associée. Donc, si j’écris (sin x), ce n’est pas le sinus du symbole x que je veux obtenir, mais le sinus de la valeur associée à x. (Cependent, il y a des symboles qui sont évalués à eux-même : par exemple, « nil » ou les keywords tels comme :a, :b, etc.)

    Il arrive qu’on ne veut pas évaluer une expression : par exemple, on veut travailler avec le symbole x plutôt qu’avec la valeur associée. Alors on met ' avant l’expression (ce qui est une abréviation de (quote x)). 'x est évalué au symbol x.

    Donc, 1 et '1 est la même chose: « 1 » veut dire « évaluer le nombre 1 en obtenant 1 », alors que « '1 » signifie « ne pas évaluer le nombre 1 en obtenant la valeur littérale 1 ». D’habitude, on n’ecrit pas ' avant un nombre.

    3. En Common Lisp, toutes les variables sont déclarées, et les operateurs d’affectation (tels comme setf, setq) changent les valeurs déjà existentes. Ainsi, le compilateur devait t’avertir que b était une variable indéfinie. D’habitude, on déclare les variables à l’aide de let, let* et ainsi de suite.

    Donc, le code plus idiomatique serait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    (defun new-or (&rest b)
      (let ((liste b))
        (if (member 1 liste) 1 0)))
    ce qui est équivalent à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    (defun new-or (&rest b)
      (if (member 1 b) 1 0))
    En ce qui concerne les autres langages lisp sur mac, j'ai essaye et j'ai renonce assez vite pour ne pas dire presque immédiatement car on part tout de suite dans toute une série de manipulations informatiques avant d'avoir un truc qui marche effectivement qui pour le non informaticien que je suis paraissent un surcroit de problèmes, c'est pour cela que j'ai adopte LispWorks que j'ai pu utiliser immédiatement.
    Lispworks, Clozure CL, SBCL et d’autres, c’est le même langage, Common Lisp. Il est assez facile d’écrire du code portable. Je comprends bien qu’un environnement de développement prêt à emploi est pratique, mais l’existence des alternatives libres est au moins rassurante. À propos, il existe aussi un environnement récent qui est libre, Portacle : https://shinmera.github.io/portacle/

  6. #6
    Futur Membre du Club
    Homme Profil pro
    chercheur en biologie théorique
    Inscrit en
    Avril 2017
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : chercheur en biologie théorique
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2017
    Messages : 6
    Points : 5
    Points
    5
    Par défaut remerciements
    Bonjour.

    Je te remercie des tes explications.

    En fait, j'ai appris Le_Lisp tout seul et je n'étais pas préoccupe par tout ce que tu m'expliques. J'avais hate de voir tourner les machines formelles que je venais de trouver et ai pris très vite la mauvaise habitude de taper des instructions jusqu'a ce que cela marche , ce que permet facilement un langage interprèté. Tout cela doit faire hérisser les cheveux des personnes compétentes et soucieuse de bonne programmation.

    Merci

    J-P Moulin

  7. #7
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 101
    Points : 5 849
    Points
    5 849
    Par défaut
    Citation Envoyé par JPMoulin Voir le message
    Hier soir, je parcourais "GNU Emacs 24.1 Lisp Reference Manual" je suis tombe sur un exemple similaire a ce que je cherchais
    [snip]
    En ce qui concerne les autres langages lisp sur mac, j'ai essaye et j'ai renonce assez vite pour ne pas dire presque immédiatement car on part tout de suite dans toute une série de manipulations informatiques avant d'avoir un truc qui marche effectivement qui pour le non informaticien que je suis paraissent un surcroit de problèmes, c'est pour cela que j'ai adopte LispWorks que j'ai pu utiliser immédiatement.
    Bonjour JP,

    je suis également sur mac depuis 1986.

    J'ai programmé en LOGO sur Goupil en 1983, ainsi qu'en Le_Lisp depuis 1984 sous SMX, Multics, VAX/Unix, Mac (system 5), Sun, Sparc..., en Common Lisp/CLOS depuis 1987 sur Mac, Next, Sun, Sparc... et en emacs-lisp depuis 1983 sur Vax/Unix, Sun, Sparc, PC (windows ou linux) et mac.

    Lorsque j'ai besoin de développer rapidement un prototype ne nécessitant pas d'interface sophistiquée, je le fais en emacs-lisp dans une fenêtre emacs. J'utilise M-x ielm RET qui fournit un toplevel emacs-lisp tout à fait convenable.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 36
    Dernier message: 15/05/2013, 14h44
  2. Macro-fonction avec nombre de paramètres non fixé
    Par miasseu dans le forum Macro
    Réponses: 2
    Dernier message: 31/08/2012, 17h36
  3. Réponses: 0
    Dernier message: 25/01/2008, 11h09
  4. Réponses: 3
    Dernier message: 05/09/2006, 01h47
  5. comment gérer un nombre non fixe de paramètres entrant ?
    Par c_moi_c_moi dans le forum SAP Crystal Reports
    Réponses: 4
    Dernier message: 28/03/2006, 13h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo