VDH-Bruno
Membres-
Compteur de contenus
1 146 -
Inscription
-
Dernière visite
-
Jours gagnés
20
Type de contenu
Profils
Forums
Calendrier
Blogs
Tout ce qui a été posté par VDH-Bruno
-
Bonsoir, Tu y étais presque… remplace les lignes suivante: (setq d1 (/ (distance ptac3 ptac4) (1+ nbr11))) (setq dist d1) Par (setq d1 (/ (distance ptac3 ptac4) (1- nbr11))) (setq dist 0) Sinon pour ce qui est d’ordre plus général tu peux regrouper tes appels à setq en un seul : (setq ptac3 (getpoint "\n Point de départ: ") ptac4 (getpoint pt1 "\n Point de fin: ") nbr (getint "\n Nombre d'aciers à inserer: ") d1 (/ (distance ptac3 ptac4) (1- nbr11)) dist 0 ang (angle ptac3 ptac4) ) Il est possible de déclarer ses variables en local de la façon suivante : (defun c:acier15 (/ ptac3 ptac4 nbr11 d1 dist ang) Et enfin tu peux également gérer l’état de la variable CMDECHO depuis ton Lisp avec les fonctions getvar & setvar tu verra ça fait plus propre sur la ligne de commande AutoCAD, dans la même veine pense également insérer un (princ) en fin de programme cela évitera de retourner la dernière valeur calculé par ta fonction sur la ligne de commande. (Ps : Pour le saut de ligne dans tes invites c’est \n ;) ) A+ [Edité le 20/7/2011 par VDH-Bruno]
-
Salut, Désolé lili2006 ce n’étais pas mon intention en intervenant sur ce post, sinon même si j’interviens peu sur ce forum et pas du tout sur les autres par manque de disponibilité, je vous lis également et j’ai pu constater ta grande maîtrise d’AutoCAD (bien meilleur que celle que j’ai des versions récentes). De plus la personnalisation (menu diesel script..) ne t’est pas étrangère non plus, donc en toute logique le Lisp est la prochaine étape :D (pour peu biensur que tu y trouve un intérêt suffisant pour y mobiliser le nombres d’heures nécessaire au démarrage). A+ Bruno
-
Salut -=micka=-, J’allais t’écrire que non en DCL, en argumentant que cela faisais bien longtemps qu’Autodesk n’écrivait plus ses boîtes de dialogue en DCL comme on pouvait en trouver sur les versions 12 , la transition ayant commencé sur la version 13 ou 14 et que depuis les version 2000 on n’en voyais plus (sauf encore peut être dans les Express). Voilà pensant que le graphisme de nos petites boites de dialogue devaient se résigner à ce petit coté désuet.. Mais j’avoue que le lien de Patrick_35 m’a ôté toutes mes certitudes sur ce point :D . (Ha ! Que je regrette de n’avoir que trop peu d’heures à consacrer au Lisp...). A+
-
Bonjour -=micka=- Oui comme te l’a dit (gile) l’emploi d’un slide pour des images non vectoriel peut être la solution, mais à l’usage tu verras que le jeu n’en vaut pas la vraiment chandelle.. Mais si tu veux tester ( car c’est toujours bien), il faut que tu insère ton image dans AutoCAD, puis tu fais un cliché (ou slide) de cette image, que tu chargera dans ta boite de dialogue en utilisant la fonction donné par (gile). Je te déconseille de vouloir faire plus qu’une « icône » en taille d’image car cela va ralentir considérablement le chargement de ta boîte de dialogue.. De plus sous forme de cliché ton image va perdre beaucoup en terme de qualité mais on peut toute fois arriver à un résultat presque satisfaisant. Cordialement,
-
Merci (gile) pour ce complément d’information (très instructif comme d’habitude), concernant les modes de sélections non documentés je l’avais soupçonné par déduction, tu viens de me le confirmer, pour le underscore je l’avais déjà remarqué (et fait un parallèle avec l’internationalisation des commandes AutoCAD), sur l’emploi de l’opérande (+) j’ignorais cette possibilité ( à l’occasion j’en testais d’autres.. histoire de voir..). Hé bien moi qui croyait en avoir déjà pas mal testé, il y a quelques mois en pensant avoir fait un bon tour d’horizon.. Avec ces nouvelles possiblitées, me voilà reparti pour une belle série.. A+ [Edité le 30/6/2011 par VDH-Bruno]
-
Merci Fraid, mais dans mon esprit je faisais référence à celles qui n'étaient pas documentées comme :L ou alors je n'ai pas tout saisi à la traduction sous google.. [Edité le 28/6/2011 par VDH-Bruno]
-
Bonjour, Je m’immisce dans la discutions, car j’aime beaucoup ce genre de post et je trouve qu’on en apprend souvent beaucoup plus dans trois lignes de codes que dans 100… Pour émuler encore un peu la routine, on peut raisonnablement imaginer que dans le cas d’une sélection précédente, il n’y a pas nécessité de la valider un peu comme dans le cas de la commande _erase. (defun c:zo (/ ss) (if (or (if (cadr (ssgetfirst)) (setq ss (ssget ":L"))) (setq ss (ssget)) ) (command "_zoom" "_object" ss "") ) (princ) ) Pour ce genre de petite fonction il n’est pas toujours nécessaire de la nommer, ou peut également en faire une fonction anonyme sous cette forme : ((lambda (ss) (command "_zoom" "_object" ss "") (princ)) (if (cadr (ssgetfirst)) (ssget ":L") (ssget) ) ) A lancer directement sur la ligne de commande ou à enregistrer dans un fichier puis à lancer par un simple glisser-déposé, à insérer dans une palette d’outil (à vérifier) ou plus simplement dans un bouton de commande. Bon comme je suis également en plein apprentissage du Lisp, j’espère que Lili2006 ne m’en voudra pas trop si je profite de l’occasion ( occasion que j’attendais) pour me faire éclairer sur un point de détail concernant le comportement des fonctions ssgetfirst & ssget Car même si les expressions : Retourne toutes 2 un jeu de sélection, j’avais déjà remarqué en les triturant qu’ils n’étaient pas de même valeurs, je m’explique : -Pour (ssget) passé en argument, le jeu est considéré comme « clos » et ne nécessite pas de validation pour continuer l’exécution (d’ailleurs la validation à déjà eu lieu lors de sa création) -Pour (cadr (ssgetfirst)) passé en argument, le jeu de sélection est considéré comme « ouvert » (cas du code proposé par (gile)) en ce sens que dans la fonction appelante la possibilité de le compléter est possible, sinon il faut le valider pour le clore et continuer l’exécution du programme. Je crois par expérience avoir compris la différence de comportement entre les deux jeux de sélection retourné, par contre je comprends moins bien le fait qu’à l’évaluation des fonctions toutes deux retourne un jeu de sélection ou il n’est pas possible de distinguer leur spécificité. Pour ce qui est de l’expression (ssget ":L") que j’ai utilisé et pour rendre à césar ce qui revient à césar je l’avais déjà remarqué dans des lignes de codes écrites par Patrick-35 (à qui je dis une fois de plus merci), si j’ai saisie l’intérêt que l’on pouvait faire de l’expression ":L" dans ssget je n’ai jamais trouvé de documentation la concernant alors si des fois ils en avaient d’autres que je devrais connaître... Cordialement VDH-Bruno [Edité le 28/6/2011 par VDH-Bruno]
-
Challenge 33 (liste <-> arbre)
VDH-Bruno a répondu à un(e) sujet de (gile) dans Pour aller plus loin en LISP
Bonjour, Chalenge oblige, un petit point me titillais, je n’étais pas totalement satisfait de ma version bv:lst2tree. Je donne donc une nouvelle version optimisant les appels de fonctions ( modification d’un appel que je qualifiais de fainéant), et hop + 10% au benchmark :D , et au traçage des fonctions ça fait tout de même plus beau.. ;) (defun bv:lst2tree (lst / tree etete) (defun tree (lst) (cond ((null lst) nil) ((= (caar lst) (caadr lst)) ((lambda (x) (cons (cons (caar lst) (tree [b](cons (cdar lst) (car x)))[/b]) (cdr x))) (etete [b](cdr lst)[/b]) ) ) (T (cons (car lst) (tree (cdr lst)))) ) ) (defun etete (lst) (if (= (caar lst) (caadr lst)) ((lambda (acc) (cons (cons (cdar lst) (car acc)) (cdr acc))) (etete (cdr lst)) ) (cons (list (cdar lst)) (tree (cdr lst))) ) ) (tree lst) ) Ps: Me voilà un peu plus à la hauteur du chapeau bas de (gile) -
Challenge 33 (liste <-> arbre)
VDH-Bruno a répondu à un(e) sujet de (gile) dans Pour aller plus loin en LISP
Merci (gile) je tempérerai tout de même en rappelant qu’il m’aura tout de même fallu 6 mois.. :casstet: Et avouer que si tu ne m’avais pas fait comprendre certains concepts clef du Lisp, je chercherai encore.. Alors chapeau bas à toi également !.. ;) -
Challenge 33 (liste <-> arbre)
VDH-Bruno a répondu à un(e) sujet de (gile) dans Pour aller plus loin en LISP
Bonjour, Je revisite ce challenge étant bien incapable à l’époque d’écrire la fonction réciproque bv:lst2tree ( même si j’avais l’intuition qu’une autre voie bien plus simple était possible…) Je publie donc aujourd’hui ma solution, elle utilise deux fonctions mutuellement récursives afin d’économiser des allers et retours inutiles dans le traitement de la liste fourni en argument ( au benchmark le traitement est 2 fois plus rapide). (defun bv:lst2tree (lst / tree etete) (defun tree (lst) (cond ((null lst) nil) ((= (caar lst) (caadr lst)) ((lambda (x) (cons (cons (caar lst) (tree (car x))) (cdr x))) (etete lst) ) ) (T (cons (car lst) (tree (cdr lst)))) ) ) (defun etete (lst) (if (= (caar lst) (caadr lst)) ((lambda (acc) (cons (cons (cdar lst) (car acc)) (cdr acc))) (etete (cdr lst)) ) (cons (list (cdar lst)) (tree (cdr lst))) ) ) (tree lst) ) Pour le fun, je donne également une version plus «fonctionnelle» de bv:tree2lst que celle donné précédemment ( au passage j’ai corrigé cette version), contrairement à la version précédent la liste lst ne se construit plus à la descente mais à la remonté des appels.. (defun bv:tree2lst (tree) (cond ((null tree) nil) ((atom tree) tree) (T ((lambda (a d) (cond ((and (atom a) d)(mapcar '(lambda (x) (cons a x)) d)) ((or (atom a) (atom (car a))) (cons a d)) (T (append a d)) ) ) (bv:tree2lst (car tree)) (bv:tree2lst (cdr tree)) ) ) ) ) -
Merci (gile) pour l’info ai_sysvar je ne connaissais pas, je vais y jeter un œil.
-
Bonsoir, Au départ un petit peu dans le même esprit que (gile) en voulant aider des plus débutants que moi, je publie ma routine de sauvegarde et de restauration des variables AutoCAD. Je pense que ce post et le bon endroit pour (inutile de multiplier les doublons). ;; ******* SAUVEGARDE & RESTAURATION DES VARIABLES AUTOCAD ******* ;; --------------------------------------------------------------- ;; (bv:sr_var lvar) VDH-Bruno ;; Routine de Sauvegarde et de Restauration des VARiables AutoCAD. ;; --------------------------------------------------------------- ;; Description: ;; L'argument lvar est une liste de variables AutoCAD ou nil. ;; Si lvar est vrai la fonction sauvegarde l'état des variables ;; passées en argument, si lvar vaut nil la fonction restaure ;; leurs états antérieurs. ;; --------------------------------------------------------------- ;; Exemples: ;; (bv:sr_var '(CMDECHO OSMODE CECOLOR)) ;Sauvegarde les variables ;; (bv:sr_var nil) ;Restaure les variables ;; --------------------------------------------------------------- ;; Notes: ;; Pendant la phase d'écriture et de débogage d'un prog, il peut ;; être interréssant de précéder l'expression (setq res_lvar nil) ;; d'un point virgule. (defun bv:sr_var (lvar) (if lvar (setq *res_lvar* (mapcar '(lambda (x) (cons x (cons (getvar x) ()))) lvar) ) (progn (mapcar '(lambda (l) (setvar (car l) (cadr l))) *res_lvar*) (setq *res_lvar* nil) ) ) ) ;| variante sans progn dans le if (defun bv:sr_var (lvar) (if lvar (setq res_lvar (mapcar '(lambda (x) (cons x (cons (getvar x) ()))) lvar) ) ((lambda (lst) (mapcar '(lambda (l) (setvar (car l) (cadr l))) lst) (setq res_lvar nil) ) res_lvar ) ) ) |; C’est une fonction que j’aime bien (du 2 en 1) simple d’utilisation et qui accepte des listes de variables. Il est possible de la localiser, et l’appeler au début de votre programme avec la liste des variables à sauvegarder, par exemple : (bv:sr_var '(CMDECHO OSMODE CECOLOR BLIPMODE PLINEWID)) Par la suite dans le déroulement de votre programme vous modifiez l’état de ces variables comme bon vous semble. Et en sortie (ainsi que dans votre routine d’erreur) vous rappelez la fonction comme ceci. (bv:sr_var nil) Et l’état initial de vos variables sera restauré. Bon j’ai bien conscience que cela n’a rien de révolutionnaire, mais il ne me semblait pas avoir vu ces lignes de codes dans le forum (je peux me tromper..). Avant de publier j'ai voulu confronter mon code à ce qui se faisait sur le forum et je suis tombé sur ce post, visiblement la logique ici privilégie plutôt de faire du SAVE-SET que du SAVE-RESTORE donc même si j’ai une préférence pour mon code précédent, je me suis livré à l’exercice en m’inspirant du code (gile), tout en essayant de garder la philosophie du mien.. Ce qui donne ceci du 3 en 1 ( SAVE-SET-RESTORE) sous forme de liste d’arguments.. ;; ********* SAVE & SET & RESTORE LES VARIABLES AUTOCAD ********** ;; --------------------------------------------------------------- ;; (bv:ssr_var lvar) VDH-Bruno ;; Sauvegarde, Modifie et de Restaure les VARiables AutoCAD. ;; --------------------------------------------------------------- ;; Description: ;; L'argument lvar est une liste de variables AutoCAD à ;; sauvegarder (et à modifier), si lvar vaut nil la fonction ;; restore leurs états initial. ;; --------------------------------------------------------------- ;; Exemples: ;; (bv:ssr_var '(("CMDECHO" 0);Sauve et modifie la variable à 0 ;; (OSMODE 119) ;Sauve et modifie la variable à 119 ;; (CECOLOR) ;Sauve (sans modifier la variable) ;; (TOTO) ;Alert et ignore l'erreur ;; ) ;; ) ;; (bv:ssr_var nil) ;Restore l'état des variables ;; --------------------------------------------------------------- ;; Remarques: ;; A tout moment dans votre programme vous pouvez rappeler la ;; fonction bv:ssr_var pour lui ajouter de nouvelle variable à ;; sauvegarder (et à modifier). Si par erreur vous rappelez la ;; fonction avec une variable déjà sauvegardé, elle sera seulement ;; modifié. ;; La fonction tolère également les syntaxes stringp ou symbolp ;; comme nom de variable, du type -> 'CECOLOR ou "CECOLOR" ;; --------------------------------------------------------------- (defun bv:ssr_var (lvar / fun) ;; Prédicat recherche ele dans list à 1 profondeur (defun fun (ele lst) (cond ((member ele (car lst)) T) ((null lst) nil) (T (fun ele (cdr lst))) ) ) (if lvar ;; si lvar vrai construire ou compléter *res_lvar* (setq *res_lvar* (append (apply 'append (mapcar '(lambda (x / var) (cond ;; si x est un atom et pas une variable AutoCAD renvoi nil ((or (atom x) (not (getvar (car x)))) (alert (strcat "\n (bv:ssr_var) Erreur: variable AutoCAD rejetée: " (vl-princ-to-string x) ) ) ) ;; si pas de fun (member) ((not (fun (vl-princ-to-string (car x)) *res_lvar*) ) ;; mémoriser la variable (setq var (list 'setvar (vl-princ-to-string (car x)) (getvar (car x)) ) ) ;; si (cdr x) modifier la variable (if (cdr x) (setvar (car x) (cadr x)) ) ;; retourne la variable (list var) ) ;; si (cdr x) modifié la variable et renvoi nil ((cdr x) (setvar (car x) (cadr x)) nil) ) ) lvar ) ) *res_lvar* ) ) ;; si lvar vaut nil restaurer l'état des variables (progn (mapcar 'eval *res_lvar*) (setq *res_lvar* nil)) ) ) J’espère de n’avoir pas trop compliqué les choses par rapport à mon intention première, en espérant également de ne pas avoir fait de grosse erreur de logique dans les and cond et if. Il y a peut être moyen de simplifier un peu je m’y pencherai dessus à tête reposé, aux premiers testes ça à l’air de tenir la route. A+ Bruno (Comme d'hab toutes critiques, remarques ou suggestions sont le bienvenue) [Edité le 27/5/2011 par VDH-Bruno]
-
Programmation fonctionnelle (valeur du prédicat)
VDH-Bruno a répondu à un(e) sujet de VDH-Bruno dans Débuter en LISP
Bonsoir, Moi non plus je ne pense pas m’étendre d’avantage sur cette aspect de la programmation (je ne veux pas faire de prosélytisme), je dirai simplement que si je m’essaie à la programmation fonctionnel, c’est parce que c’est ce qui caractérise le Lisp (bien qu’AutoLISP soit 'multi-paradigme' comme l’a précisé (gile)), avec le peu de recul que j’ai, je reste persuadé de 2 choses : En 1 – Qu’il n’est pas fondamentalement pas plus difficile d’apprendre la programmation fonctionnel que la programmation impérative pour quelqu’un qui par de zéro comme moi. En 2 – Que par la suite il est certainement plus facile de passer de la programmation fonctionnelle à la programmation impérative (si besoin est), la réciproque me semblant moins évidente… Pour ce qui est de la récursion je conseil ce tut sur le site du zero (pour ceux qui en recherche), il n’est pas spécifique au Lisp (php et Ocalm) mais suffisamment général et détaillé pour être facilement transposable, de plus il y de bonnes réflexions sur son emploie, sa soi-disant lenteur d’exécution et les débordements de pile (ce qui est vrai en AutoLISP, mais pas forcément dans d’autres langages…). Sinon un grand bravo Patick_35 pour ces quelques lignes, que je me suis empressé de convertir en fonction (au passage atoms-family à 0 améliorera par 5 le traitement de la fonction). Fonction sur laquelle je pensais bien plancher un jour mais pas si vite.. Je suis heureux de ton intervention qui m’aura donné l’occasion de gagner un temps précieux. ;; --------------------------------------------------------------- ;; (bv1:auditfun 'fun) ;; Retourne la liste des nouvelles variables et fonctions non ;; localisées. Suite à l'appel de fun ;; --------------------------------------------------------------- ;; Adapté d'un code de Patrick_35 (source CADXP) (defun bv1:auditfun (fun) ((lambda (lst) (eval fun) (vl-remove-if '(lambda (x) (member x lst)) (atoms-family 0)) ) (atoms-family 0) ) ) ;| ;; variante qui a l’avantage de ne pas pister la variable lst ;; pour ceux que cela gênerai (defun bv1:auditfun (fun / lst) (setq lst T lst (atoms-family 0) ) (eval fun) (vl-remove-if '(lambda (x) (member x lst)) (atoms-family 0)) ) |; Pour tester (defun n*n () (defun carre (n) (* n n) ) (carre (getreal "Saisissez un nombre: ")) ) Teste Sinon une autre façon de faire (propre et élégante). ;; --------------------------------------------------------------- ;; (bv2:auditfun) ;; Retourne la liste des nouvelles variables et fonctions non ;; localisées. ;; --------------------------------------------------------------- ;; Adapté d'un code de Patrick_35 (source CADXP) ;; Exemple: ;; (bv2:auditfun) ;1er appel liste l'état actuel des symboles ;; ;définie ;; (Mafonction) ;fonction à analyser ;; ;; (bv2:auditfun) ;2éme appel renvoie les symboles nouvellement ;; ;crée ;; Note: L'argument lst en également listé. (defun bv2:auditfun () ((lambda (lst) (if lst (progn (setq lstsym nil) (vl-remove-if '(lambda (x) (member x lst)) (atoms-family 0)) ) (setq lstsym (atoms-family 0)) ) ) lstsym ) ) ;| ;; variante qui ne liste pas l'argument lst (defun bv2:auditfun (/ lst) (if *lstsym* (progn (setq lst *lstsym* *lstsym* nil ) (vl-remove-if '(lambda (x) (member x lst)) (atoms-family 0)) ) (setq lst T *lstsym* (atoms-family 0) ) ) ) |; Teste A+ Bruno [Edité le 25/5/2011 par VDH-Bruno] -
Programmation fonctionnelle (valeur du prédicat)
VDH-Bruno a répondu à un(e) sujet de VDH-Bruno dans Débuter en LISP
Bonjour, Oui (gile), tu as raison c’était comme cela que je l’avais vu à l'origine, la coquille ligne 4 de mon code (cons (car lst) (bv:l=npe (1- n) (cdr lst))) en atteste, ce qui est une étourderie de copier-colller, la bonne version est la suivante : (defun bv:l=npe (n lst / fun) (defun fun (n lst) (if (< 0 n) (cons (car lst) (fun (1- n) (cdr lst))) ) ;_ Fin de if ) ;_ Fin de defun (if (< n (length lst)) (fun n lst) lst ) ;_ Fin de if ) ;_ Fin de defun Cette version (et donc la fonction auxiliaire fun) résulte d’un effort de logique pour optimiser les ressources déployer dans le calcul du prédicat, logique qui dit que si n est inférieur à la longueur de la liste, il n’y aura jamais besoin de vérifier l’existence de lst et il n’y aura plus besoin du and dans le calcul du prédicat précédent tous les appels de fun, contrairement à la version que tu publie. Je te le concède d'avance l’optimisation est plus que discutable (perte de la concision, calcul de length sur tous les éléments de lst ect..) mais en général sur les grandes listes avec des valeurs de n élevé on s’y retrouve.. En guise de clin d’œil à Patrick_35 (que je remercie au passage pour ses routines et ses lignes de codes dans lesquels il m’arrive de puiser allègrement). La même version écrit avec un repeat.. (defun bv2:l=npe (n lst / res) (if (< n (length lst)) (progn (repeat n (setq res (cons (car lst) res) lst (cdr lst) ) ) (reverse res) ) lst ) ) A+ (Ps : Dans l’exemple pa:c-member il y a une coquille, en lisp une expression peut être considéré comme un atome ou une liste. La fonction /= (tout comme la fonction =) ne s’applique qu’aux atomes (nombres, chaines, symboles). Quant aux fonctions < > >= et <= qui sont des comparateurs numériques elles ne s’appliquent qu’exclusivement aux nombres et aux chaînes). (/= (list 1 2) (list 1 2)); retourne T (/= (list 1 3) (list 1 2)); retourne T -
Programmation fonctionnelle (valeur du prédicat)
VDH-Bruno a répondu à un(e) sujet de VDH-Bruno dans Débuter en LISP
Bonsoir, Tout d’abord, je n’ai pas pris assez de recul avec mon teste au benchmark, tel qu’il était formulé j’effectuais la comparaison entre une fonction lambda et une fonction member à chaque répétion et pas l’évaluation de l’optimisation réalisé dans mon code. Le bon teste ressemblerai plus à une comparaison de ce type, désolé pour l’étourderie. Oui (gile), on pouvait faire différemment, d’ailleurs j’avais déjà la structure de base dans une fonction quasi similaire bv:l=npe (il ne restait qu’à la retoucher un peu). ;; --------------------------------------------------------------- ;; (bv:l=npe n lst) ;; --------------------------------------------------------------- ;; Renvoie une Liste égal aux N Premiers Eléments. ;; Exemple : ;; (bv:l=npe 0 '(a b c d e)) renvoie nil ;; (bv:l=npe 2 '(a b c d e)) renvoie (A B) ;; (bv:l=npe 8 '(a b c d e)) renvoie (A B C D E) (defun bv:l=npe (n lst / fun) (defun fun (n lst) (if (< 0 n) (cons (car lst) (bv:l=npe (1- n) (cdr lst))) ) ;_ Fin de if ) ;_ Fin de defun (if (< n (length lst)) (fun n lst) lst ) ;_ Fin de if ) ;_ Fin de defun Que j’avais écrit en même temps que la fonction bv:l-npe. ;; --------------------------------------------------------------- ;; (bv:l-npe n lst) ;; --------------------------------------------------------------- ;; Renvoie une Liste des privés de ses N Premiers Eléments, ;; Exemple : ;; (bv:l-npe 0 '(a b c d e)) renvoie (A B C D E) ;; (bv:l-npe 2 '(a b c d e)) renvoie (C D E) ;; (bv:l-npe 8 '(a b c d e)) renvoie nil (defun bv:l-npe (n lst) (cond ((< 3 n) (bv:l-npe (- n 4) (cddddr lst))) ((< 2 n) (bv:l-npe (- n 3) (cdddr lst))) ((< 1 n) (bv:l-npe (- n 2) (cddr lst))) ((< 0 n) (bv:l-npe (- n 1) (cdr lst))) (T lst) ) ;_ Fin de cond ) ;_ Fin de defun Pour écrire une fonction sublist qui travaille directement sur la tête de liste et non sur l’indice (ou position) des élèments comme tu l’a fait dans la tienne. Mais pour en revenir à c-member, j’ai voulu tenter une approche différente surtout depuis hier lorsque je me suis aperçu que ces fonctions avaient déjà été évoqué dans le challenge n° 22 ( Au passage dure dure de passer après vous mais cela doit être un peu normal, je n’ai que 10 ans de retard à rattraper). Mais j’avoue que ta fonction trunc à l’avantage d’être linéaire dans sa performance contrairement à la mienne qui dépend de l’âge du capitaine (c.a.d. du nombre d’éléments identique constituant lst). Merci pour le retour, convaincu par ta reflexion sur la lisibilité. Patrick_35, non pas forcément d’ailleurs en général en tant qu’apprenant, je m’efforce de coder les deux histoires de ne pas m’enfermer complément dans un style plus que dans un autre. Mais j’avoue avoir un gros penchant pour le côté fonctionnelle que je privilégie toujours en première approche et effectivement comme l’a dit (gile) des qu’il est question de prédicat dans un processus répétitif difficile en programmation fonctionnelle d’éviter de faire une récursive. Au passage je trouve ce type de fonctions beaucoup plus souple pour le traitement et le travail sur les listes (qui sont d’ailleurs elles-mêmes des structures récursives), prenons en exemple la fonction pa:c-member et la fonction gc:trunc pour moi c’est le même traitement à la différence prés qu’avec une boucle while tu ne peux conser ta liste que dans un sens ce qui t’oblige à un reverse. Alors qu’en récursif tu peux conser en descendant dans tes appels (avec un argument suplémentaire en guise d’accumulateur) cas de la recursion terminal et la tu devrais également employer un reverse, ou alors tu peux conser en remontant tes appels récursif (ce que fait la fonction trunc) cas de la recursion enveloppante et la plus besoin de reverse. Il est également très difficile d’explorer avec while des listes de profondeur inconnue, alors qu’avec la récursion multiple rien de plus facile : ;; --------------------------------------------------------------- ;; (bv:profondeur lst) ;; --------------------------------------------------------------- ;; Renvoie la profondeur maxi d'une liste. ;; Exemples : ;; (bv:profondeur '(a b c d e)) renvoie 1 ;; (bv:profondeur '((a b) c (((d e))))) renvoie 4 ;; (bv:profondeur '()) renvoie 0 (defun bv:profondeur (lst) (if (atom lst) 0 (max (1+ (bv:profondeur (car lst))) (bv:profondeur (cdr lst)) ) ;_ Fin de max ) ;_ Fin de if ) ;_ Fin de defun De plus les fonctions de boucle tel que repeat while me semble limiter aux imbriquations de répétition, alors que la récursion permet de les croiser voir ici pour la dernière publication en date de ce type de boucle. Pour finir j’ai jamais réussie à me servir correctement des outils de débogage de Visual Lisp, alors que en récursif il y a la fonction trace. Je crois que l’on reste fortement influencé par le style de ses débuts et quant j’ai commencé l’aventure Lisp, je me suis très vite intéressé à cette aspect de la programmation (le côté fonctionnelle), au début par défit, maintenant c’est plus par « jeux ». A+ VDH -
Bonjour, J’arrive un peu près à ce que je veux réaliser dans ce style de programmation maintenant je suis au stade ou je souhaite optimiser un peu mes codes.. Il y a un point qui me pose encore quelques difficultés (ou incertitudes), c’est comment récupérer la valeur d’un prédicat de façon à le passer comme argument de l’appel récursif ? Pour illustrer ma difficulté je vous présente un code simple qui résume bien le cas de figure que je veux exposer. A savoir réaliser la fonction complémentaire à la fonction member : ;; --------------------------------------------------------------- ;; (bv:c-member expr lst) -> fonction complémentaire de member ;; Recherche une expression dans une liste et renvoie les éléments ;; précédents la première expression trouvé. ;; Si la liste ne contient pas l'expression recherchée, la liste ;; initiale est retourné. ;; --------------------------------------------------------------- ;; Exemples: ;; (bv:c-member 'c '(a b c d c e)) -> (A B) ;; (bv:c-member 'z '(a b c d c e)) -> (A B C D C E) ;; (bv:c-member 'a '(a b c d c e)) -> nil (defun bv:c-member (expr lst / fun) (defun fun (lst) (if (member expr lst) (fun (cdr (member expr lst))) lst ) ;_ Fin de if ) ;_ Fin de defun (reverse (fun (reverse lst))) ) ;_ Fin de defun La fonction donne bien le résultat escompter, toute fois il y a une optimisation possible dans l’appel récursif de fun à savoir que l’expression ( member expr lst) et executé 2 fois, une fois comme prédicat de la fonction if et une second fois comme argument dans l’appel récursif de fun. Une voie possible mais qui n’est pas celle que je recherche, c’est de stocker avec setq la valeur de ( member expr lst) de la façon suivante : (defun fun (lst / x) (if (setq x (member expr lst)) (fun (cdr x)) lst ) ;_ Fin de if ) ;_ Fin de defun La solution que je recherche c’est de réalisé la même chose avec un appel de fonction, actuellement j’arrive à coder ça avec la fonction lambda, en m’inspirant de ce qui m’a été montré dans mon poste sur le triangle de pascal. (defun bv:c-member (expr lst / fun) (defun fun (lst) ((lambda (l) (if l (fun (cdr l)) lst ) ;_ Fin de if ) ;_ Fin de lambda (member expr lst) ) ) ;_ Fin de defun (reverse (fun (reverse lst))) ) ;_ Fin de defun Question est ce la bonne méthode ou a-t-il d’autres solutions (ou optimisation possible).. Car au petit jeu du benchmark les résultats ne sont pas forcément là: (Note: bv:c-member1 bv:c-member2 bv:c-member3 sont les évaluations respectives des codes dans l'ordre de leurs présentations. On peut remarquer que bv:c-member2 est naturellement optimisé contrairement à bv:c-member3, l'appel à lambda consomme visiblement plus de ressource que l'évaluation redondante du (member expr lst) dans bv:c-member1, le mieux est il l'ennemi du bien???). Tous les avis sont les biens venus, d’avance merci. A+ VDH
-
Bonsoir Tramber Soit pas trop impatient (humour), bien que la fonction getcoption tourne à quelques exceptions près (sur lesquelles je dois réfléchir pour les contourner de façon à la rendre publiable), je me suis déjà dispersé sur d’autres notamment une qui retourne toute les options de commandes possibles pour le niveau en cours (c’est gadget mais ça m’amuse), on y voit toute les incohérences dans les invites de commande et l’absence de rigueur dans les options de commande possibles.. A titre d’exemple (un parmi d’autres) en réponse à ma fonction : (op:toutes '("_pline" "0,0" "LA" "3" "" "100,0" "") "LA") On explore toute les options de commande possible après l’instruction : (vl-cmdf "_pline" "0,0") Et ma fonction retourne ("TT" "REPERAGE" "LONGUEUR" "LIGNE" "LARGEUR" "DEMI-LARG" "ARC") Pour les valeurs de retour : TT (c’est l’instruction d’activation du repérage temporaire) et REPERAGE on comprend. LONGUEUR, LARGEUR, DEMI-LARG, ARC rien à dire, c’est les options classique. LIGNE tiens, je ne savais pas que c’était une option possible et pour cause l’instruction n’est reliée à aucune action !!! Pour AutoCAD à ce stade l’invite propose : L’absence de l’option de command ANNULER en retour de la fonction montre le peu de rigueur de l’invite, car comment annuler un segment qui n’existe pas à ce stade (c’est comique), surtout qu’ils y avaient bien pensé chez Autodesk pour l’instruction CLORE. Et des fonctions aussi gadget, j’en ai plein la tête et hélas trop peu de temps à y consacrer.. Cordialement,
-
Bonsoir, Oui, je me doutais bien en postant qu’il y aurait plus performant avec du VL-REMOVE-IF (ou -IF-NOT) ou autres, et je ne prend pas du tout cela comme une critique bien au contraire.. :D (c’est la confrontation à d’autres codes qui font progresser). Les fonctions VL je m’en sers très peu, car je les ai juste parcourus et pas encore vraiment trituré (sauf deux ou trois), elles ne sont donc pas encore bien toutes acquises. De plus je suis dans une phase d’écriture de codes et dans ces moments j’aime bien aller au plus rapide pour aboutir et vérifier mes hypothèses et raisonnements (je prends pas le temps de chercher dans les fonctions que je ne me suis pas encore approprié), il n’y a qu’après avoir maîtrisé mon sujet (ou que je n’ai pas abouti) que je regarde si il n’y avait d’autres façons de faire en me documentant pour m’améliorer. Pour bv:lst-type (en plus d’être un bon exercice) c’était l’occasion pour moi de mettre en pratique une petite explication donné ici par Patrick_35 sur le or et le and. Sinon ces quelques fonctions notamment ar-1:n ( dont on devrait prochainement trouver la version fonctionnel) me rendent de grands services dans un fichier dans lequel je me livre à quelques élucubrations (ou jeux) sur les possibilités des fonctions command, vl-cmdf, getcname et de la variable LASTPROMPT. De tous ce fatras (ou fonctions gadgets) il devrait malgré tout sortir une fonction getcoption qui (comme sa parente getcname pour les commande AutoCAD) renvoi les options de commande internationalisé, et ce lorsque j’aurais un peu de disponibilité (et/ou fini de jouer :mad: ) pour qu’elle puisse avoir complètement le comportement voulu.. A+ [Edité le 20/4/2011 par VDH-Bruno]
-
Bonjour, Quelques fonctions de traitement de liste écritent récemment, c'est pas du grand art, mais bon si des fois ça peut servir.. ;; --------------------------------------------------------------- ;; (bv:lst-type lst ltype flag) ;; Sélectionne ou supprime d'une liste des éléments par type. ;; --------------------------------------------------------------- ;; Arguments: ;; lst => Une liste d'élément. ;; ltype=> Une liste des types d'éléments à sélectionner. ;; flag => Si flag=nil les éléments sont supprimés de la liste ;; Si flag= T seul les éléments spécifiés sont gardés ;; ;; Retourne: Une liste en fonction des conditions spécifiés. ;; ;; Exemples : ;; (bv:lst-type '(1.0 "Un" 2 toto) '(SYM REAL) T) ;; => (1.0 TOTO) ;; (bv:lst-type '(1.0 "Un" 2 toto) '(SYM REAL) nil) ;; => ("Un" 2) (defun bv:lst-type (lst ltype flag) (apply 'append (mapcar '(lambda (x) (cond (flag (if (apply 'or (mapcar '(lambda (y) (= (type x) y)) ltype)) (list x))) (T (if (not (apply 'or (mapcar '(lambda (y) (= (type x) y)) ltype))) (list x))) ) ) lst ) ) ) ;; --------------------------------------------------------------- ;; ar-1:n => Arrangement à Répétition de 1 à n (Version itérative) ;; --------------------------------------------------------------- ;; Argument: Une liste de symboles (d'éléments) ;; Retourne: Tous les arrangements de 1 à n ;; Exemple : ;; (ar-1:n '(A B C) 2) ;; => ((A) (B) (C) (A A) (A B) (A C) (B A) (B B) (B C) (C A) (C B) (C C)) (defun ar-1:n (l n / lst res) (setq lst '(nil)) (repeat n (setq res (append res (setq lst (apply 'append (mapcar '(lambda (x) (mapcar '(lambda (y) (cons x y)) lst) ) l ) ) ) ) ) ) ) ;; --------------------------------------------------------------- ;; (bv:str-num lst) ;; Retourne une liste de chaînes non numérique. ;; --------------------------------------------------------------- ;; Argument: Une liste composé de chaînes de caractères. ;; Retourne: Une liste de chaînes exclusivement non-numérique. ;; Exemple : (bv:str-num (list "1.0" "Un" "-2E11" "Deux" "")) ;; Retourne ("Un" "Deux" "") (defun bv:str-num (lst) (apply 'append (mapcar '(lambda (x) (if (not (or (= (type (read x)) 'INT) (= (type (read x)) 'REAL)) ) (list x))) lst) ) ) Cette dernière me permet lorsque je me sert de ma routine d'arrangement pour combiner des chaînes, à exclure de ces dernières les chaînes représentants des valeurs numérique aux yeux d'AutoCAD comme "-1E11" ou "123" par exemples. _$ (bv:str-num (mapcar '(lambda (x) (apply 'strcat x)) (ar-1:n '("A" "E" "F" "1" "3" "-") 2))) ("A" "E" "F" "-" "AA" "AE" "AF" "A1" "A3" "A-" "EA" "EE" "EF" "E1" "E3" "E-" "FA" "FE" "FF" "F1" "F3" "F-" "1A" "1E" "1F" "1-" "3A" "3E" "3F" "3-" "-A" "-E" "-F" "--") _$
-
Bonsoir Tramber Bon là je vais essayer de le faire de mémoire (lecture vieille de 6 mois) car je n’ai pas réussi à retrouver le sujet que j’avais en tête même après 2 heures de recherche.. Par le terme réentrant, il fallait entendre qu’il n’est pas possible en Lisp (il me semble) d’invoquer une commande écrite en Lisp à partir d’une autre commande écrite en Lisp (attention je parle de commande et plus de fonction Lisp). L’explication en question portait notamment sur l’invocation de façon transparente d’une commande Lisp à partir d’une autre commande écrite en Lisp (d’où le terme de réentrance en Lisp). Alors que d’autres langages sous AutoCAD le permettraient notamment le C dans une limite de 4 niveaux, sur ce dernier point je fait peut être erreur, je ne suis sur de rien.. Si il fallait approfondir le sujet j’espère que d’autres intervenants viendraient à mon secours car à mon niveau je ne peux actuellement aller plus loin dans l’explication. A+
-
Bonsoir Oui, tu peux enregistrer ton dessin en DXF puis l'ouvrir avec un éditeur de texte, mais pas sur que celà t'aide beaucoup.. A+
-
J’espère également ne pas me tromper en disant que Tramber fait peut être une confusion entre la programmation fonctionnel et la notion de « réentrance » qui il me semble est limité en Lisp.. Mais bon je dis cela de mémoire car je n’ai jamais eu l’occasion de me confronté cette notion, j’ai lu à ce sujet (c’était à mes débuts en me documentant mais je ne sais plus ou) une explication de serge camiré ou de kamal boutura il me semble.. Explication que je n’étais pas encore à l’époque en mesure d’assimiler, dommage que je ne puisse la retrouver, je suis sur que cela me parlerai plus maintenant.. Je dis cela mais je dois avouer que c’est très flou pour moi.. A+
-
Bonsoir, Effectivement je pense avoir conclu un peu hâtivement hier soir. J'avais également un peu avancé sur la question depuis avant de vous lire. Merci (gile) pour cette brillante démonstration et explications, l’emploi du quote explique bien des choses, je m’en veux un peu de ne pas avoir percuté plus vite.. surtout que tu l’avais déjà fait ici à mon intention .. A+ Bruno (Ps: Désolé de t'avoir fait radoter..) [Edité le 12/4/2011 par VDH-Bruno]
-
Bonsoir Tramber, Pourquoi pas ! Une explication qui en vaut une autre, j’entend ce que tu dis mais cela ne me convainc que très moyennement, personnellement je crois plus en un bug.. command est une fonction lisp, l’expression (type command) retourne SUBR Sinon personnellement je formulerai plutôt l’un applique la fonction command à tous les éléments de la liste, et l’autre évalue la liste «quoté » (command "_pline" '(0 0) "LA" 3 "" '(100 0) "D" "" 4 '(0 100) "C")) Mais je ne vois pas de réelle différence dans ces 2 formulations car : (defun apply2 (F L) (eval (cons F L)) ) ;_ Fin de defun _$ (apply '+ '(1 2 3)) 6 _$ (apply2 '+ '(1 2 3)) 6 _$ (apply 'strcat '("a" "b" "c")) "abc" _$ (apply2 'strcat '("a" "b" "c")) "abc" A+ Bruno
-
Bonjour à tous, Voilà j’ai eu un petit souci dans l’écriture d’un de mes codes avec l’emploi de la fonction apply, petit souci que j’ai facilement contourné avec l’emploi de cons + eval. Pour résumer,soit une liste d’arguments variables et quelconques (mais toujours valide) du type : (setq argmt '("_pline" '(0 0) "LA" 3 "" '(100 0) "D" "" 4 '(0 100) "C")) Que je souhaite soumettre à la fonction command Avec cette syntaxe, cela ne fonctionne pas.. (apply 'command argmt) Alors qu’avec la suivante tous se déroule comme espéré. (eval (cons 'command argmt)) Bizare, jusqu’ici j’ai toujours pensé que (apply ‘fun liste) étais équivalent à (eval (cons ‘fun liste)), hé bien non. Amusant n’est ce pas… :casstet: Surtout si je me reporte à l’aide qui dit que : A croire que la fonction command fait exception à la règle.. ;) Cordialement Bruno
