Aller au contenu

Messages recommandés

Posté(e)

Bonjour,

 

Bon pour ceux qui auraient suivi je m’exerce en ce moment à maîtriser la récursion mutelle. En gros je travaille sur les concaténations de car et cdr pour écrire ma fonction avec en entré la concaténation c" adada"d à réaliser et la liste sur la quelle appliquer la fonction.

 

Fonction qui accessoirement permettrait de dépasser les 4 niveaux de concaténation (dont la limite de concaténation serait dépendent de la pile d’appel,). On peut faire plus simple mais c’est à titre d’entrainement ;) .

 

Au passage ce petit exercice ma fait prendre conscience que les concaténation de car & cdr, c’est comme l’arabe ça ce lit de droite à gauche.. ou alors comme ça s’écrit pour ceux qui ne lisent pas l’arabe (ce qui n’était pas aussi évident au départ dans mon esprit)

 

(cddar ‘((a b c d) (e) f (g f))) retourne (C D)

équivalent à (cdr (cdr (car ‘((a b c d) (e) f (g f)))))

Ce qui revient à lire a en premier puis d puis d

 

 

Tout ceci est titre d’introduction car ce n’est pas vraiment mon propos du jour.

 

Mon propos concerne une bizarrerie constaté dans le choix de mon non de fonction, qui m’a amené sur le terrain des choix de nom de fonction pour finir sur une réflexion plus général sur la valeur retourné par l’évaluation d’une fonction.

 

 

La bizarrerie en question :

 

Je ne livre que les lignes nécessaires à sa compréhension, n’étant pas encore satisfait de mon code :

 

 (defun c...r (atm lst / conca ) 
(setq conca atm) 
...
) 

 

 C 
_$ (c...r 'ada lst) 
ADA 
_$ 

 

Analysons un peu

 _$ C     -->  #
_$ c.    -->  #
_$ c..   -->  #
_$ c...d -->  #
_$ c.toto -->  #

 

Le fait d’introduire un point dans le non d’une fonction, fait ignorer tout les caractères qui suivent.. (pas la peine d’essayer avec d’autres caractères, j’ai testé pour vous c’est le seul qui à cette propriété)

 

 

Continuons et généralisons un peu avec les écritures suivantes :

 _$ car  -->  #
_$ car.o-->  #
_$ (car.toto '(a b))
A
_$ etc.. ect..

 

Le fait d’introduire un point dans l’appel d’un non de fonction, ne gène en rien son évaluation. (pas la peine d’essayer avec d’autres caractères, j’ai encore testé pour vous c’est toujours le seul qui à cette propriété).

 

Les questions :

1 Le saviez vous ?

2 Pourquoi le point et seulement lui ?

3 Y a-t-il moyen de tirer partie de cette propriété ? Si oui dans qu’elle cas ?

(Pour ma part, j’ai pas trouvé)

 

 

Le choix d’un nom de fonction

Voilà tout ceci m’a amené à m’interroger également sur cette question, ce que j’ai réussi à synthétiser :

 

Extrait de l’aide version R14 (je sais ça date un peu)

Aucune distinction majuscules/minuscules n'est faite dans les noms de symbole ; ils peuvent par ailleurs comporter n'importe quelle séquence de caractères alphanumériques ou de notation, à l'exception des caractères suivants: ( ) . ' " ; . Un nom de symbole ne peut pas être constitué uniquement de caractères numériques. … ce manuel utilise le terme symbole pour désigner un nom de symbole contenant des données statiques, telles que les fonctions inhérentes et les fonctions définies par l'utilisateur.

considérez le préfixe de nom de fonction S:: comme étant "réservé" (Cf S::STARTUP)

Si le symbole est constitué de six caractères au maximum, il est stocké directement dans le noeud de nom de symbole. Sinon, un espace de stockage des chaînes est alloué dans le tas pour mémoriser le nom et le noeud de nom de symbole contient un pointeur pour désigner cette chaîne. En conséquence, il est conseillé d'utiliser des noms de symboles de six caractères au maximum pour limiter l'espace de stockage des chaînes nécessaire et la fragmentation du tas.

 

Ce que j’ai testé et qui est accepté malgré la définition de l’aide.

 _$ (setq A' 1) 
1 
_$ (setq A. 1) 
1 

 

Pour la longueur des noms de fonctions, j’ai supposé qu’il en allait de même que pour les noms de symbole.

Sinon pour le reste dite moi si je suis passé à coté de quelques choses.. (histoire que je n’ai plus à me pencher sur cette question du choix des noms de fonctions).

 

 

Et pour finir, une petite question subsidiaire (la question et pas vital je vous rassure), au cas ou vous connaitriez la réponse:

 

Valeur retourné par l’évaluation d’une fonction.

 

Si j’évalue cdr & ma fonction c...d (renommé depuis)

 _$ cdr
#
_$ c...d 
#

 

Je suppose:

SUBR et USUBR représente leur type

CDR et C leur nom

@0fb0ef78 et @186d4adc certainement une adresse (pointeur)

 

Que représente cette adresse? En quoi peut servir ce type d’information ? Dans quel cas en tirer profit ?

 

 

Je sais, ça fait beaucoup de questions, j’abuse peut être un peu et si il n’y a pas de réponses, je ne me formaliserai pas, j’ai conscience que ce ne sont que des points singuliers qui ne sont pas bloquant dans mon apprentissage du LISP.

 

 

Cordialement Bruno

(Ps : rectification il n’y a pas que le point qui à ces propriétés l’apostrophe aussi à une ou deux nuance prés)

 

Edit 1

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

Oupss! J’ai peut être posté un peu vite, en relisant après coup le post de (gile) Éléments de syntaxe AutoLISP je m’aperçois que certain thèmes font doublons sur les caractères autorisés, mais d’autres sont complémentaires..)

 

 

[Edité le 9/11/2010 par VDH-Bruno]

 

[Edité le 9/11/2010 par VDH-Bruno]

Apprendre => Prendre => Rendre

Posté(e)

Salut,

 

Concernant les caractères à ne pas utiliser dans les noms de symboles, tu as trouvé (deux fois...).

Ils ne sont pas tous "interdits" pour les mêmes raisons : " ( ) marquent un début ou fin de chaine ou de liste, ; un commentaire et . et ' provoquent ce que tu as pu remarquer : ce qui suit ces caractères (et les caractères eux même) sont ignorés.

_$ (setq a. 12)
12
_$ a
12
_$ (setq a' 15)
15
_$ a
15

 

Je rappelle au passage que dans les langages fonctionnels les fonctions et données sont "au même niveau" :

(setq car nil) annihile la fonction car

(setq car cdr) attribue cdr à car

 

F# (le nouveau langage fonctionnel de la plateforme .Net que je sui en train de découvrir) utilise le même mot clé : let pour attribuer une valeur ou une fonction à un symbole.

 

Concernant le nombre de caractères, il me semble que les choses ont changées depuis l'arrivée de Visual LISP (version 2000), en tout cas nombre de nouvelles fonctions prédéfinies dépassent largement les 6 caractères.

Dans tous les cas, la gestion et les capacités de mémoire ont énormément évolué depuis cette époque et je pense qu'il est préférable d'utiliser des noms de fonctions explicites et préfixées pour éviter les conflits AutoLISP ne présentant pas d'autre moyen de localiser les symboles qu'à l'intérieur des fonctions.

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

Posté(e)

Bonsoir,

 

(gile) une fois de plus je te remercie pour tes précisions, concernant les noms de symbole, je suis convaincu de l’utilisation de nom explicite.

 

 

Pour l’explication complète sur les noms de symbole court donné à l’époque dans l’aide de la R14 :

Manuel de personnalisation -> Partie II -- Référence AutoLISP -> Chapitre 15 -- Gestion de la mémoire -> Notes techniques -> Mémorisation des symboles

La structure de la mémoire d'AutoLISP utilise les pointeurs de façon intensive. L'utilisation des noeuds est systématique, tout étant décrit dans la structure nodale. Le simple fait d'affecter une valeur à un symbole dont le nom est de taille importante, nécessite deux noeuds : le premier pour mémoriser le nom du symbole, l'autre pour mémoriser sa valeur.

Si le symbole est constitué de six caractères au maximum, il est stocké directement dans le noeud de nom de symbole. Sinon, un espace de stockage des chaînes est alloué dans le tas pour mémoriser le nom et le noeud de nom de symbole contient un pointeur pour désigner cette chaîne. En conséquence, il est conseillé d'utiliser des noms de symboles de six caractères au maximum pour limiter l'espace de stockage des chaînes nécessaire et la fragmentation du tas.

 

 

La raison du pourquoi donné à l’époque dans l’aide

Manuel de personnalisation -> Partie II -- Référence AutoLISP -> Chapitre 15 -- Gestion de la mémoire -> Espace nodal

Un noeud est une structure en mémoire qui peut représenter n'importe quel type de données AutoLISP. Actuellement, AutoLISP utilise des noeuds de 12 octets.

 

En recherchant dans l’aide de la 2011 (que je déchiffre très difficilement) ce chapitre semble effectivement avoir disparu depuis.. (Chapitre certainement obsolète depuis)

 

Sinon pour info dans ce fameux chapitre15 il y avait également d’intéressantes explications sur l’emploi de : gc vmon alloc expand et le verrouillage des fonctions nommé en mémoire dans « les tables de page » (en avouant tout de même que beaucoup de ces info me passe encore au dessus de la tête).De toute façon tout ceci ne doit plus être trop d’actualité également..

 

 

 

Pour ce qui concerne la récursion, j’avance bien, l’exercice auquel je me livre sur les concaténations de car et cdr est essentielle dans ma compréhension des listes, j’ai l’impression qu’il m’a ouvert les yeux sur ce qu’est le LISP.

Ce sujet Ces listes qui n'en sont pasque j’avais qualifié d’intéressant, me parait maintenant fondamental, je regrette seulement qu’il n’ai pas l’écho qu’il mériterai.. Si tu le permet je pense que j’essaierai un jour de le développer d’avantage..

 

Pour résumer car et cdr en mode récursif, je dirai que les conditions d’arrêt sont :

L’ atome pour car

nil pour cdr

J’ai découvert tout cela grâce à la représentation des listes en arbre binaire suite à ce fameux post. Arbres binaires dont j’ignorai encore l’existence hier, qui ont l’avantage de mettre en évidence l’implication du nil dans la structure des listes.

 

Salutations Bruno

 

Apprendre => Prendre => Rendre

Posté(e)
Ce sujet Ces listes qui n'en sont pasque j’avais qualifié d’intéressant, me parait maintenant fondamental, je regrette seulement qu’il n’ai pas l’écho qu’il mériterai..

 

Hello

Peu de gens développent et viennent sur ce forum quand on fait la somme.

Peu de gens développent au quotidien

Peu de gens se passionnent pour ce qu'il y a dérrière les outils. C'est déjà assez long d'apprendre à bien les utiliser.

Enfin tout le monde ne poste pas de réponses à un sujet alors qu'ils le lisent et s'y intéressent.

 

On a 1000 choses à faire dans une vie. Et a priori ici, vous êtes deux à avoir mis ces sujets en n

:cool:

Pour ce sujet : j'ai bien lu cette documentation à l'époque (2001) puis ai parcouru le web afin d'en apprendre davantage et enfin me suis plongé dans un long apprentissage des outils. Il était déjà bien difficile de tout cerner (Vlisp venait d'apparaitre). et d'avoir un point de départ. Il y a bientôt 10 ans, point de telles conversations ou documentation sur internet. Nous sommes d'accord ? Je ne connais pas une seule page en français traitant d''un symbole point dans le nom d'une fonction hors d'ici et remontant à quelques années.

Donc c'est très intéressant d'observer une personne qui se penche pour nous sur des fondamentaux.

Il y aura des retombées !

 

Modestement, je travaille en écoutant FIP, France Inter ou mes disques. Mais si je tombe sur une émission France Culture qui m'intéresse, je l'écoute ! (Et je ne téléphone pas forcement au standard pour dire que c'était super !).

Bureau d'études dessin.

Spécialiste Escaliers

Développement - Formation

 

./__\.
(.°=°.)
Posté(e)

Bonjour,

 

La structure de la mémoire d'AutoLISP utilise les pointeurs de façon intensive. L'utilisation des noeuds est systématique, tout étant décrit dans la structure nodale. Le simple fait d'affecter une valeur à un symbole dont le nom est de taille importante, nécessite deux noeuds : le premier pour mémoriser le nom du symbole, l'autre pour mémoriser sa valeur.

Si le symbole est constitué de six caractères au maximum, il est stocké directement dans le noeud de nom de symbole. Sinon, un espace de stockage des chaînes est alloué dans le tas pour mémoriser le nom et le noeud de nom de symbole contient un pointeur pour désigner cette chaîne. En conséquence, il est conseillé d'utiliser des noms de symboles de six caractères au maximum pour limiter l'espace de stockage des chaînes nécessaire et la fragmentation du tas.

 

Je connaissais cette recommandation faite dans la doc de la R14, et de ce fait, actuellement je continu (la plus-part du temps) à appliquer inconsciemment cette limitation lors de la déclaration de mes variables.

 

Concernant le nombre de caractères, il me semble que les choses ont changées depuis l'arrivée de Visual LISP (version 2000), en tout cas nombre de nouvelles fonctions prédéfinies dépassent largement les 6 caractères.

 

Ce qui à changé c'est la quantité d'espace alloué, donc plus vraiment un problème.

 

il y avait également d’intéressantes explications sur l’emploi de : gc vmon alloc expand

Seul (vmon) a disparu (je crois me rappeler que ça permettait d'accéder à la mémoire étendue pour l'usage du lisp)

Les autres existent toujours. Les expliquer...

Je ne suis pencher qu'une fois sur l'utilisation de ces fonctions pour essayer d'améliorer la capacité de traitement de fonctions récursives. (Ce qu'on gagne d'un coté, on le perd de l'autre. Le réglage par défaut est un bon compromis. Il est guère utile de se pencher sur ces fonctions)

 

Mais pour imager: il est plus facile et rapide de retrouver un terme dans un calepin, que dans un dictionnaire.

Donc en terme de performance, normalement, l'évaluation ne devrait être que plus rapide

 

J'ai donc fais un test pour me rendre compte de l'influence de l'usage de variables longues (et essayé d'interpréter).

 

Je l'ai répété plusieurs fois et constaté la même consommation d'espace à chaque fois.

 

Le test:

((lambda ( / n) (gc) (mem)
(setq n 0)
(repeat 1000
(set (read (strcat "v" (itoa (setq n (1+ n))))) (+ n (* (1+ (sqrt 5)) 0.5)))
)
(mem)))

le retour

"; GC calls: "38"; GC run time: "46" ms"

"\nDynamic memory segments statistic:\n""

PgSz Used Free FMCL Segs Type\n"

512 6 248 122 2 lisp stacks

256 904 626 191 6 bytecode area

4096 89 1 1 6 CONS memory

32 776 1207 1207 1 ::new

4096 [surligneur]16 [/surligneur] 119 14 9 DM Str

4096 119 31 6 10 DMxx memory

128 3 508 508 1 bstack body

"Segment size: "65536", total used: "35", free: "3

"; GC calls: "39"; GC run time: "46" ms"

"\nDynamic memory segments statistic:\n""

PgSz Used Free FMCL Segs Type\n"

512 6 248 122 2 lisp stacks

256 904 626 191 6 bytecode area

4096 89 1 1 6 CONS memory

32 776 1207 1207 1 ::new

4096 [surligneur]19 [/surligneur] 116 14 9 DM Str

4096 145 20 6 11 DMxx memory

128 3 508 508 1 bstack body

"Segment size: "65536", total used: "36", free: "2

nil

19-16=3 pages mémoires utilisées pour DM Str AVEC des variables courtes.

 

le second test

((lambda ( / n) (gc) (mem)
(setq n 0)
(repeat 1000
(set (read (strcat "v_tttttttttttttttttttttt" (itoa (setq n (1+ n))))) (+ n (* (1+ (sqrt 5)) 0.5)))
)
(mem)))

 

Le retour

"; GC calls: "48"; GC run time: "62" ms"

"\nDynamic memory segments statistic:\n""

PgSz Used Free FMCL Segs Type\n"

512 6 248 122 2 lisp stacks

256 904 626 191 6 bytecode area

4096 89 1 1 6 CONS memory

32 776 1207 1207 1 ::new

4096 [surligneur]16[/surligneur] 149 14 11 DM Str

4096 124 41 9 11 DMxx memory

128 3 508 508 1 bstack body

"Segment size: "65536", total used: "38", free: "3

"; GC calls: "49"; GC run time: "62" ms"

"\nDynamic memory segments statistic:\n""

PgSz Used Free FMCL Segs Type\n"

512 6 248 122 2 lisp stacks

256 904 626 191 6 bytecode area

4096 89 1 1 6 CONS memory

32 776 1207 1207 1 ::new

4096 [surligneur]31[/surligneur] 134 14 11 DM Str

4096 149 31 9 12 DMxx memory

128 3 508 508 1 bstack body

"Segment size: "65536", total used: "39", free: "2

nil

31-16=15 pages mémoires utilisées pour DM Str AVEC des variables longues.

 

J'interprète DM Str comme un tableau de dimensionnement de chaine ce caractères pour l'affectation de nom de symbole.

 

Je pense qu'il n'est pas idiot de continuer à tenir compte de ces vieilles recommandations.

 

En aparté, regarde la propriété particulière d'une paire pointé.

 

(car '(70 . 1)) et (cdr '(70 . 1))

le cdr retourne un atome.

 

[Edité le 11/11/2010 par bonuscad]

Choisissez un travail que vous aimez et vous n'aurez pas à travailler un seul jour de votre vie. - Confucius

Posté(e)

Bonsoir,

 

Tramber : Tout à fait d’accord avec toi.

On a 1000 choses à faire dans une vie.

Et généralement pour en faire 1001, c’est bien souvent au détriment du temps de sommeil, tout en essayant de rester dans la limite du raisonnable.. ;)

 

Bonuscad : Merci de ces précisions, et bien vu l’aparté.. :cool:

(car '(70 . 1)) et (cdr '(70 . 1))

le cdr retourne un atome.

Ah ces fameuses paires pointées comme je ne travaille pas avec, je n’ai pas toujours le réflexe de les intégrer dans mes raisonnements.

 

Apprendre => Prendre => Rendre

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é