Aller au contenu

Messages recommandés

Posté(e)

Salut,

 

Un sujet récent m'a donné envie de mettre en oeuvre un processus proche de ce qu'on appelle en anglais precomputation.

L'implémentation de ce mécanisme en AutoLISP à été décrit dans TheSwamp par Michael Puckket (MP) ici et .

 

Il s'agit donc, dans un soucis de performances, de n'effectuer certaines opérations qu'au premier appel d'une fonction et d'utiliser les résultats de ces opérations aux appels suivants, ces résultats étant enregistrés dans la fonction.

 

Prenons un exemple simple.

Chargez et exécutez la fonction ci-dessous.

Elle vous demande votre nom et affiche une boite d'alerte pour vous dire personnellement bonjour.

Rien de bien extraordinaire jusque là, mais si vous rappelez HELLO, la boite d'alerte s'affichera en spécifant votre nom mais sans vous l'avoir redemandé.

 

(defun c:hello ()
 (eval
   (list
     'defun
     'c:hello
     '()
     (list
'alert
(strcat "\nBonjour " (getstring "\nVotre nom: "))
     )
     '(princ)
   )
 )
 (c:hello)
)

 

Ceci est possible en LISP parce qu'un programme LISP est une liste et qu'un programme LISP peut construire et évaluer une liste.

 

Examinons le code ci-dessus. À l'intérieur d'une définition de fonction classique, on trouve deux expressions :

un appel à eval auquel est passé une construction de liste en argument.

un appel à la fonction elle même.

 

Toute la magie réside dans la construction de cette liste. Certains éléments sont "quotés" et ne seront pas évalués par la fonction list d'autres ne le sont pas et seront donc évalués lors de la construction de cette liste.

 

Si on évalue l'expression suivante dans la Console de l'éditeur ou en ligne de commande :

(list
 'defun
 'c:hello
 '()
 (list
   'alert
   (strcat "\nBonjour " (getstring "\nVotre nom: "))
 )
 '(princ)
)

On est invité à entrer son nom (ici : "Toto") et on obtient :

(DEFUN C:HELLO nil (ALERT "\nBonjour Toto") (PRINC))

Ici, seule l'expression :

(strcat "\nBonjour " (getstring "\nVotre nom: "))

a été évaluée.

 

En évaluant cette liste avec eval, la fonction c:hello se redéfinit elle même avec le nom entré par l'utilisateur "en dur", puis s'appelle elle même pour afficher la boite d'alerte :

(defun c:hello (/ s)
 (DEFUN C:HELLO nil (ALERT "\nBonjour Toto") (PRINC))
 (c:hello)
)

 

On peut, bien sûr, utiliser ce processus pour des fonctions plus utiles. Par exemple, lire un fichier texte pour récupérer toutes les lignes dans une liste qui devrait être utilisée par une autre fonction qui peut être appelée plusieurs fois.

 

(defun readLines (/ filename)
 (eval
   (list
     'defun
     'readLines
     '()
     (if (setq filename (getfiled "Choisir le fichier" "" "*" 0))
(list
  'quote
  ((lambda (/ sel file line ind lst)
     (setq file (open filename "r"))
     (while (setq line (read-line file))
       (setq lst (cons line lst))
     )
     (close file)
     lst
   )
  )
)
'()
     )
   )
 )
 (readLines)
)

Au premier appel de (readLines), l'utilisateur est invité à spécifier un fichier, celui-ci est lu et une liste contenant toutes les lignes du fichier est créée. aux appels suivants (readLines) la liste, stocké "en dur" dans la fonction, sera directement retournée.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Salut,

le mécanisme est vraiment astucieux, d'une subtilité bien lispienne ...

par contre je me pose la question de l'avantage par rapport à un code plus balourd avec

une variable globale, du genre :

(if (not GC-Ton-Nom) (setq GC-ton-Nom (getstring "Ton nom ?")))

dans ton cas, tu vas économiser le if not, mais tu vas compliquer la mise en place d'une option de relecture dont l'utilisateur peut avoir besoin.

 

Maintenant il y a peut être un avantage d'occupation mémoire lors de la lecture de fichiers volumineux:

!c:hello

#<SUBR @0000000034e5cae8 C:HELLO>

 

le résultat est compilé,

alors que ma variable globale sera une liste.

 

Je m'interroge, mais c'est sympa de nous l'avoir fait découvrir ...

Gérald

----------------------------------------------------------------------

Site: https://www.g-eaux.fr

Blog: http://g-eaux.over-blog.com

Posté(e)

Salut Gérard,

 

Je ne pense pas qu'il y ait de réelle différence en terme de performances avec l'utilisation d'une variable globale.

 

C'est juste pour montrer un moyen d'éviter de se servir de variables globales en utilisant une voie plus typée "programmation fonctionnelle", et puis, pour "aller plus loin en LISP".

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Posté(e)

Salut

 

Intéressante l'astuce. Je pense comme Gérald qu'avec une variable, cela ne change pas grand-chose, mais la démarche est intelligente.

 

Merci

 

@+

Les Lisps de Patrick

Le but n'est pas toujours placé pour être atteint, mais pour servir de point de mire.

Joseph Joubert, 1754-1824

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité