Une macro qui crée des macros?

Tout ce qui concerne l'utilisation ou l'installation de LaTeX.

Modérateur: gdm_tex

Règles du forum
Merci d'éviter le style SMS dans vos messages et de penser à utiliser la fonction Recherche avant de poster un message. Pour joindre des fichiers à vos messages, consulter ce sujet.
> Penser à utiliser les balises Code pour poster du code.

Une macro qui crée des macros?

Messagepar jeans » Vendredi 15 Décembre 2006, 09:46

Bonjour,
je me demandais si je pourrais créer une macro \generateur qui me créerait d'autres macros automatiquement selon les paramètres que je lui donnerais.

Par exemple, est-ce qu'un truc du genre

Code: Tout sélectionner
\newcommand{\generateur}[2]{\def\var#1{#2}


qu'on utiliserait avec

Code: Tout sélectionner
\generateur{toto}{bravo} \vartoto


(et qui afficherait bravo) a une chance de fonctionner. Est-ce que c'est absolument impossible ou est-ce que je m'y prends mal.
Merci d'avance.
jeans
Déca-utilisateur
 
Messages: 40
Inscription: Vendredi 24 Novembre 2006, 14:44

Publicité

Messagepar la main gauche » Vendredi 15 Décembre 2006, 10:01

C'est possible.
Tu t'y prends mal.

Essaie plutôt
Code: Tout sélectionner
\def\generateur#1#2{%
  \begingroup
  \toks0={#2}%
  \edef\next{\expandafter\noexpand\csname var#1\endcsname{\the\toks0 }}%
  \expandafter\endgroup\next
}
la Main Gauche
la main gauche
Méga-utilisateur
 
Messages: 274
Inscription: Jeudi 30 Mars 2006, 07:44
Localisation: selon l'idéal de la liberté

Messagepar jeans » Vendredi 15 Décembre 2006, 13:14

:o ouah, là j'suis dépassé.
J'ai essayé de l'utiliser avec
Code: Tout sélectionner
\generateur(toto,bravo) \vartoto
mais il râle. Il me dit
! ! Undefined control sequence.
\next ->\var(
{t}
l.11 \generateur(toto,bravo) \vartoto
?

Et comme j'ai perdu le contrôle avec le code que tu me proposes...
jeans
Déca-utilisateur
 
Messages: 40
Inscription: Vendredi 24 Novembre 2006, 14:44

Messagepar jeans » Samedi 16 Décembre 2006, 10:02

Personne n'a d'idée?
jeans
Déca-utilisateur
 
Messages: 40
Inscription: Vendredi 24 Novembre 2006, 14:44

Messagepar kilébo » Samedi 16 Décembre 2006, 11:09

Je comprends pas.

Tu dis que tu vas essayer ça :
Code: Tout sélectionner
\generateur{toto}{bravo} \vartoto


et tu essaies ça :
Code: Tout sélectionner
\generateur{toto,bravo} \vartoto


Je doute que cela va marcher.
A une erreur de calcul et de raisonnement prêt, tout cela doit être correct.
kilébo
Téra-utilisateur
 
Messages: 1059
Inscription: Samedi 22 Avril 2006, 11:08
Localisation: Région Parisienne
Statut actuel: Actif et salarié

Messagepar jeans » Samedi 16 Décembre 2006, 11:24

En fait je n'ai utilisé ni l'un ni l'autre, j'ai essayé
Code: Tout sélectionner
\generateur(toto,bravo)

et aussi
Code: Tout sélectionner
\generateur toto,bravo

Car le code que me proposait la main gauche utilisait \def et pas \newcommand.
Il me semblait que c'était ainsi qu'on utilisait une macro à paramètres définie par \def.
Me suis-je lamentablement trompé dans l'utilisation de la macro qu'il me proposait?
jeans
Déca-utilisateur
 
Messages: 40
Inscription: Vendredi 24 Novembre 2006, 14:44

Messagepar kilébo » Samedi 16 Décembre 2006, 11:26

Les paramètres de \def se présentent pareil que \newcommand. Essaie donc avec les accolades.
A une erreur de calcul et de raisonnement prêt, tout cela doit être correct.
kilébo
Téra-utilisateur
 
Messages: 1059
Inscription: Samedi 22 Avril 2006, 11:08
Localisation: Région Parisienne
Statut actuel: Actif et salarié

Messagepar jeans » Samedi 16 Décembre 2006, 11:35

Je viens de tester \generateur{toto}{bravo} et l'erreur est la même

Code: Tout sélectionner
! ! Undefined control sequence.
\next ->\vartoto
      {bravo}
jeans
Déca-utilisateur
 
Messages: 40
Inscription: Vendredi 24 Novembre 2006, 14:44

Messagepar la main gauche » Lundi 18 Décembre 2006, 17:05

Ah j'ai oublié un \def au début du next, ça donne ça:
Code: Tout sélectionner
\def\generateur#1#2{%
  \begingroup
  \toks0={#2}%
  \edef\next{\def\expandafter\noexpand\csname var#1\endcsname{\the\toks0 }}%
  \expandafter\endgroup\next
}

%
% ça marche comme ça:
%
\generateur{toto}{Toto le héros}
\vartoto
la Main Gauche
la main gauche
Méga-utilisateur
 
Messages: 274
Inscription: Jeudi 30 Mars 2006, 07:44
Localisation: selon l'idéal de la liberté

Messagepar jeans » Lundi 18 Décembre 2006, 17:45

:thumbup: :thumbup: :thumbup:
GENIAL!!!!
Je me doutais bien que ça ne tournait pas à cause d'une toute petite erreur. Alors de colère et de frustration de ne pouvoir modifier seul ton code, je viens de commander le Texbook. J'espère que ça m'aidera à passer un cap. Car je plafonne dès qu'on attaque ce genre de code.
En tout cas mille mercis pour ton aide, je sens que ça va me faire gagner pas mal de temps.
Maintenant à moi de jouer, j'adapte cette macro et c'est parti.
Merci encore.
jeans
Déca-utilisateur
 
Messages: 40
Inscription: Vendredi 24 Novembre 2006, 14:44

Messagepar jeans » Mardi 19 Décembre 2006, 00:15

Ok, avec tout ça, j'ai bien avancé.
Maintenant il me reste un dernier problème à régler.
Imaginons le code suivant:

Code: Tout sélectionner
\newcommand{\generateur}[2]{%
\def\chiffre{#2}
  \begingroup
  \toks0={{\chiffre} est mon chiffre préféré}%
  \edef\next{\def\expandafter\noexpand\csname var#1\endcsname{\the\toks0 }}%
  \expandafter\endgroup\next
}

\generateur{toto}{5}
\generateur{tata}{3}

\vartoto \par \vartata



Ca tourne mais ça me donne
3 est mon chiffre préféré
3 est mon chiffre préféré

Ce que je pense comprendre d'ailleurs car il stocke (dans la variable \chiffre) 5 puis 3.
Et quand il compile à la fin (que ce soit pour vartoto ou vartata), il le fait deux fois avec \chiffre qui a une valeur égale à 3

Alors que le code suivant me donne exactement ce que je veux:
Code: Tout sélectionner
\newcommand{\generateur}[2]{%
\def\chiffre{#2}
  \begingroup
  \toks0={{\chiffre} est mon chiffre préféré}%
  \edef\next{\def\expandafter\noexpand\csname var#1\endcsname{\the\toks0 }}%
  \expandafter\endgroup\next
}


\generateur{toto}{5}\vartoto \par

\generateur{tata}{3}\vartata


5 est mon chiffre préféré
3 est mon chiffre préféré


Comment puis-je obtenir le 2e résultat si je suis obligé de déclarer toutes mes variables (\generateur...) au début pour ne les appeler (\vartoto\vartata...) qu'à la fin?


J'ai fait ce que j'ai pû pour être clair mais ce n'est pas facile.
Merci à tous ceux qui ont pris la peine de me lire, d'y réfléchir voire de me répondre.
Et puis merci encore à la main gauche pour les solutions précieuses déjà apportées.
jeans
Déca-utilisateur
 
Messages: 40
Inscription: Vendredi 24 Novembre 2006, 14:44

Messagepar la main gauche » Mercredi 20 Décembre 2006, 14:50

jeans a écrit:J'ai fait ce que j'ai pû pour être clair mais ce n'est pas facile.


Si tu veux l'expliquer à un systéme informatique, il faut sans doute commencer à l'éclaircir assez pour pouvoir l'expliquer calmement à quelqu'un. Dans le TeXbook TeX rappelle que les ordianteurs sont doués pour faire ce qu'on leur dit mais pas pour lire dans les pensées (au passage, si tu penses que ce livre peut t'être utile, c'est un excellent investissement, TeX est un systéme assez compliqué).

Pour essayer d'éclaircir la situation, je vais commencer par une question : que veux-tu dire lorsque tu écris `\def\chiffre{#2}' je ne comprends pas le but de cette définition.

Sinon essaie
Code: Tout sélectionner
\tracingmacros=2
\tracingcommands=2


dans ton fichier, cela ajoute des informations dans le fichier LOG produit à côté de TeX.
la Main Gauche
la main gauche
Méga-utilisateur
 
Messages: 274
Inscription: Jeudi 30 Mars 2006, 07:44
Localisation: selon l'idéal de la liberté

Messagepar jeans » Mercredi 20 Décembre 2006, 22:47

Le seul moyen d'être clair est d'être précis.
Alors je rentre un peu dans les détails en prenant un exemple factice mais plus précis.
Je veux créer des questionnaires avec les réponses toujours du même type.
Par exemple ce questionnaire aurait pour but de s'entraîner à faire des additions.
Je veux donc créer une macro \questionnaire et une macro \addition.
La première s'occupe de gérer le questionnaire avec 2 questions et 2 réponses.
La deuxième (grâce à tes conseils) s'occupe de créer les questions et les réponses selon les paramètres et les besoins.
Voici le code.

Code: Tout sélectionner
\documentclass[a4paper,10pt]{article}
\usepackage{t1enc}\usepackage[francais]{babel} \selectlanguage {francais}
\usepackage{calc}
\def\questionnaire{
Questions\par
\begin{enumerate}
\item \questiona
\item \questionb
\end{enumerate}
Réponses\par
\begin{enumerate}
\item \reponsea
\item \reponseb
\end{enumerate}}

\newcounter{termea}\newcounter{termeb}\newcounter{somme}
\def\addition#1#2#3{
 \setcounter{termea}{#1}  \setcounter{termeb}{#2}\setcounter{somme}{\thetermea+\thetermeb}
  \begingroup
  \toks0={Calculer la somme $#1 + #2$}%
  \edef\next{\def\expandafter\noexpand\csname question#3\endcsname{\the\toks0 }}%
  \expandafter\endgroup\next   
  \begingroup
  \toks1={La réponse est \thesomme}%
  \edef\next{\def\expandafter\noexpand\csname reponse#3\endcsname{\the\toks1 }}%
  \expandafter\endgroup\next   
}

\begin{document}
\addition{2}{5}{a}
\addition{4}{7}{b}
\questionnaire
\end{document}


Et le problème c'est que le résultat des 2 sommes est 11 quand je compile.
Ce qui ne semble pas vraiment illogique d'ailleurs.
N'empêche que je ne sais pas bien comment régler ce problème.
Et il ne me reste que ça à régler.
Et quand ça sera fait, je fais une pause car ça m'use les neurones tout ça.

Après je vais créer d'autres macros type \multiplication ou \division ou d'autres trucs encore bien plus compliqués qui m'intéressent (car ce ne sont pas des additions que je cherche à faire et mon questionnaire comporte 2 séries de 10 questions/réponses).
Voilà, j'espère cette fois avoir été assez précis. Et j'espère aussi que la solution existe.
Merci encore de ta coopération.
jeans
Déca-utilisateur
 
Messages: 40
Inscription: Vendredi 24 Novembre 2006, 14:44

Messagepar la main gauche » Jeudi 21 Décembre 2006, 07:48

Avec ton code les deux macros reponsea et reponseb ont le même texte de remplacementà savoir, `la réponse est \thesomme' . Ta macro addition aconnaît tout ce qu'il faut au moment de l'appel pour calculer cette somme.

Tu peux remplacer
Code: Tout sélectionner
\toks1={La réponse est \thesomme}%
\edef\next{\def\expandafter\noexpand\csname reponse#3\endcsname{\the\toks1 }}%

par
Code: Tout sélectionner
\toks0={La réponse est }%
\toks1=\expandafter{\thesomme}%
\edef\next{\def\expandafter\noexpand\csname reponse#3\endcsname{\the\toks0 \the\toks1 }}%
la Main Gauche
la main gauche
Méga-utilisateur
 
Messages: 274
Inscription: Jeudi 30 Mars 2006, 07:44
Localisation: selon l'idéal de la liberté

Messagepar jeans » Jeudi 21 Décembre 2006, 15:22

J'ai essayé mais le résultat est le même.
Le problème ne réside-t-il pas dans le fait que:
Code: Tout sélectionner
\addition{2}{5}{a}

A ce moment là, \thesomme vaut 7
Code: Tout sélectionner
\addition{4}{7}{b}

Maintenant \thesomme vaut 11
Code: Tout sélectionner
\questionnaire

Et à ce moment là, que ce soit pour \reponsea ou pour \reponseb, \the somme vaut 11, donc les 2 réponses obtenues sont 11.

Pour contourner ça, je vais essayer de créer des compteurs utilisant le nom des paramètres.
Pour avoir un compteur "sommea" et et un compteur "sommeb" (en fait un compteur "somme#3").
Je vais donc essayer de créer un compteur dont le nom prend en compte le paramètre #3 (en adaptant ton code qui me permettait de créer une macro dont le nom utilisait le paramètre #3).
Mais je sens que je vais un peu galérer car je ne maitrise pas tout ce que tu y a mis.
J'essaye quand même, je sens que le but est proche.
jeans
Déca-utilisateur
 
Messages: 40
Inscription: Vendredi 24 Novembre 2006, 14:44

Messagepar jeans » Jeudi 21 Décembre 2006, 15:49

J'y suis presque.

Avec le code suivant j'obtiens \reponsea et \reponseb identiques et égales à 7:
Code: Tout sélectionner
\newcounter{termea}\newcounter{termeb}\newcounter{sommea}\newcounter{sommeb}
\def\addition#1#2#3{
 \setcounter{termea}{#1}  \setcounter{termeb}{#2}\setcounter{somme#3}{\thetermea+\thetermeb}
  \begingroup
  \toks0={Calculer la somme $#1 + #2$}%
  \edef\next{\def\expandafter\noexpand\csname q#3\endcsname{\the\toks0 }}
  \expandafter\endgroup\next   
  \begingroup
  \toks1={La réponse est }

  \toks2={\thesommea}%

\edef\next{\def\expandafter\noexpand\csname r#3\endcsname{\the\toks1 \the\toks2}}
\expandafter\endgroup\next   

\begin{document}
\addition{2}{5}{a}
\addition{4}{7}{b}
\questionnaire
\end{document}
}



Avec le même code et en remplaçant
Code: Tout sélectionner
\toks2={\thesommea}
par
Code: Tout sélectionner
\toks2={\thesommeb}
j'obtiens \reponsea et \reponseb identiques et égales à 11.

Ce qui prouve bien que j'ai réussi à créer les 2 compteurs comme je le voulais.

Je pensais gagner en remplaçant alors par:
Code: Tout sélectionner
\toks2={\thesomme#3}
mais ça ne tourne pas.

Voilà encore le moment où j'atteins mes limites.
Il me reste juste à être capable d'appeler le compteur "\thesommea" ou \thesommeb" suivant le paramètre sachant que \thesomme#3 ne passe pas.
jeans
Déca-utilisateur
 
Messages: 40
Inscription: Vendredi 24 Novembre 2006, 14:44

Messagepar la main gauche » Vendredi 22 Décembre 2006, 10:22

Il vaut mieux se débrouiller pour que le texte de remplacement de vartoto contienne la valeur de thesomme. Essaie de lire la doc du package CALC pour voir comment il faut faire. Sans ce package essaie
Code: Tout sélectionner
\documentclass[a4paper,10pt]{article}
\usepackage{t1enc}\usepackage[francais]{babel} \selectlanguage {francais}
\usepackage{calc}
\def\questionnaire{
Questions\par
\begin{enumerate}
\item \questiona
\item \questionb
\end{enumerate}
Réponses\par
\begin{enumerate}
\item \reponsea
\item \reponseb
\end{enumerate}}

\def\addition#1#2#3{
  \begingroup
  \count0=#1
  \count1=#1
  \count2=0
  \advance\count2 by \count0
  \advance\count2 by \count0
  \toks0={Calculer la somme $#1 + #2$}%
  \edef\next{\def\expandafter\noexpand\csname question#3\endcsname{\the\toks0 }}%
  \expandafter\endgroup\next   
  \begingroup
  \toks0={La réponse est }%
  \toks1=\expnadafter{\the\count2 }%
  \edef\next{\def\expandafter\noexpand\csname reponse#3\endcsname{\the\toks0 \the\toks1}}%
  \expandafter\endgroup\next   
}

\begin{document}
\addition{2}{5}{a}
\addition{4}{7}{b}
\questionnaire
\end{document}
la Main Gauche
la main gauche
Méga-utilisateur
 
Messages: 274
Inscription: Jeudi 30 Mars 2006, 07:44
Localisation: selon l'idéal de la liberté

Messagepar jeans » Mercredi 27 Décembre 2006, 02:50

Ok, ton code tourne impeccable.
J'ai voulu l'adapter sur un truc plus compliqué, et :idea: :idea: :idea: j'ai réussi.
Enfin je sors du bourbier.
Ceci dit ça reste compliqué et parfois obscur pour moi.
Je te laisse en paix désormais avec toutes mes interrogations (jusqu'aux prochaines) et je vais me coucher.
En te remerciant encore car c'était mission impossible sans ton aide.
jeans
Déca-utilisateur
 
Messages: 40
Inscription: Vendredi 24 Novembre 2006, 14:44

Messagepar la main gauche » Vendredi 05 Janvier 2007, 12:12

Y'a pas de quoi! TeX est un système complexe, et qui propose un mode de prgrammation un peu exotique. Pour la lecture du TeXbook, en ce qui concerne la programmation les chapitres 1--8 sont importants et le chapitre sur les macros bien entendu. Après il faut beaucoup s'entraîner à faire des choses simples pour arriver à faire des choses compliquées, comme pour tout. Bon courage encore!
la Main Gauche
la main gauche
Méga-utilisateur
 
Messages: 274
Inscription: Jeudi 30 Mars 2006, 07:44
Localisation: selon l'idéal de la liberté

Messagepar jeans » Jeudi 18 Janvier 2007, 19:52

Et oui... je reviens à la charge. J'ai hésité à créer un nouveau post mais je poursuis dans celui ci. Je vous propose un exemple idiot dont l'intérêt est juste technique pour tex. Je ne comprends pas ce qui se passe et ça m'ennuie. Surtout ça m'empèche de résoudre le problème.
Alors voilà une macro produit qui calcule le produit de 2 nombres:
Code: Tout sélectionner
\def\produit#1#2{
\count0=#1 \count1=#2
\multiply\count0 by \count1
\the\count0
}


Puis une macro multiplication comme suit:
Code: Tout sélectionner
\def\multiplication#1#2#3{
\count0=#1 \count1=#2
\toks0=\expandafter{\produit{\the\count0}{\the\count1}}
\edef\next{\def\expandafter\noexpand\csname testproduit#3\endcsname{\the\toks0}
}
\expandafter\next
}


Ces 2 macros étant crées, je les fais tourner avec:
Code: Tout sélectionner
\multiplication{1}{2}{a} \multiplication{1}{4}{b}
\testproduita

Et je compile. Et là je pensais obtenir 2... mais j'obtiens 4.
Alors je mets mon cerveau en marche et ... c'est là que ça coïnce.
Je me dis que, peut-être, il faudrait un begingroup...endgroup dans multiplication.
Mais je ne dois pas les mettre où il faut car j'obtiens 0 quand j'essaie.
Bref je suis coïncé. Que puis-je faire?

Remarque: pour ceux qui ont suivis le post depuis le début, je crois que la différence avec ce qui s'est passé avant (et résolu par La main gauche) est que dans multiplication on crée testproduit dans lequel on utilise une macro produit.

Merci aux lecteurs avisés pour leurs conseils.
jeans
Déca-utilisateur
 
Messages: 40
Inscription: Vendredi 24 Novembre 2006, 14:44

Suivante

Retourner vers LaTeX

 


  • Articles en relation
    Réponses
    Vus
    Dernier message

Qui est en ligne

Utilisateurs parcourant ce forum: Ahrefs [Bot], DotBot [Crawler], Google Adsense [Bot], Grapeshot [Crawler] et 29 invités