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

Discussion :

LaTeX renewcommand recursive

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 9
    Points : 5
    Points
    5
    Par défaut LaTeX renewcommand recursive
    Bonjour

    Je cherche un moyen simple de faire grandir une chaine de caractere de manière récursive en LaTeX. Quelque chose du genre en "qui marche" serait pas mal ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    \newcommand{\liste}{}
    \newcommand{\ajoute}[1]{
    \renewcommand{\liste}{\liste #1}
    }
    Le compilateur n'aime pas et me dit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TeX capacity exceeded, sorry [input stack size=5000]
    L'idée étant que chaque fois qu'on rencontre la commande \ajoute{toto}, on ajoute toto a une chaine de caractère que l'on puisse récupérer plus tard avec la commande \liste

    Si quelqu'un a une idée...merci bien

  2. #2
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Vienne (Limousin)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 344
    Points : 561
    Points
    561
    Par défaut
    Salut !

    C'est un problème classique. L'astuce est de développer "l'ancienne" commande \liste puis de la redéfinir. Tu étais sur la bonne piste, il te manquait juste le développement.

    Voici un code fonctionnel (XeLateX mais la commande fonctionne aussi avec pdfLaTeX). Petit bonus, tu peux même passer des commandes en argument.

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    % !TEX encoding = UTF-8 Unicode
    % !TEX TS-program = XeLaTeX
     
    \documentclass[french, a4paper, 12pt, oneside]{article}
     
    \usepackage{fontspec}
    \usepackage{geometry}
    \usepackage{babel}
     
     
    \makeatletter
     
    \def\liste{}
     
    \def\ajoute#1{%
    	\edef\temp@a{#1}%
    	\expandafter\expandafter\expandafter\def%
    	\expandafter\expandafter\expandafter\liste%
    	\expandafter\expandafter\expandafter{\expandafter\liste\temp@a}%
    }
     
    \makeatother
     
    \begin{document}
     
    	Contenu de liste: \liste;
     
    	Ajoute « toto » à \verb+\liste+ \ajoute{toto};
     
    	Contenu de liste: \liste;
     
    	\def\titi{titi}
    	Ajoute « titi » à \verb+\liste+ \ajoute{ \titi};
     
    	Contenu de liste: \liste;
     
    	La macro est même purement développable: \meaning\liste
     
    \end{document}
    La FAQ apporte souvent la solution aux problèmes
    Avant de demander de l'aide, pensez à faire un ECM ! Un problème bien expliqué est un problème à moitié résolu .

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 9
    Points : 5
    Points
    5
    Par défaut
    Merci Benoists !

    J'ai en effet trouvé pas mal de trucs avec ces \expandafter sans forcément trop comprendre...

    pourrais tu détailler ce que fait exactement ton développement ??

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    	\edef\temp@a{#1}%
    	\expandafter\expandafter\expandafter\def%
    	\expandafter\expandafter\expandafter\liste%
    	\expandafter\expandafter\expandafter{\expandafter\liste\temp@a}%
    }
    que fait \edef ?
    pourquoi 3 \expandafter successifs ??
    pourquoi autant de séries de 3 \expandafter ??
    Je ne comprends pas ce que fait \def si loin de \liste pour la redéfinition

    que fait exactement \meaning ??

    En tout cas je vais essayer ça ce soir !!

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 9
    Points : 5
    Points
    5
    Par défaut
    ça marche bien !! c'est presque ce que je voulais, mais la mise en forme du texte ne passe pas. En gardant ton code, et en voulant ajouter \textbf{titi}, j'ai une erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Ajoute « toto » à \verb+\liste+ \ajoute{toto};
    Contenu de liste: \liste;
     
    \def\titi{titi}
    Ajoute « titi » à \verb+\liste+ \ajoute{ \textbf{\titi}};
     
    Contenu de liste: \liste;
    erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Missing control sequence inserted Contenu de liste: \liste
    Le \meaning\liste donne (super comme fonction ! je connaissais pas) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    macro:->toto \protect \unhbox \voidb@x \bgroup \def \@nil {titi}\let
    \futurelet \@let@token \let \protect \relax \protect \edef m{bx}\protect \xdef \T1/pcr/m/n/10 {\T1/ppl/m/n/10
    }\T1/pcr/m/n/10 \size@update \enc@update titi\egroup
    et on dirait que le \textbf est pris en compte, mais il n'apparait pas sur le pdf
    (Je compile en général avec pdfLaTeX)

  5. #5
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Vienne (Limousin)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 344
    Points : 561
    Points
    561
    Par défaut
    Alors, je vais essayer de répondre dans l'ordre :

    • \edef est l'équvalent de \def sauf qu'il effectue un développement maximal sur tous le texte de remplacement. Ainsi, si tu as des commandes dans le texte de remplacement, il va les développer pour obtenir leur texte de remplacement;
    • C'est ce qu'on appelle un pont d'\expandafter. Le but est de développer les deux commandes dans la redéfinition de \liste. La commande \expandafter saute la commande qui suit et développe encore celle d'après. En alignant les \expandafter, on peut développer la commande \temp@a. Une fois développé, les \expandafter disparaissent et le curseur de lecture revient au début. Une nouvelle passe d'\expandafter permet de développer la commande \liste pour obtenir son contenu (pas simple à expliquer comme notion ...);
    • \def est loin de \liste à cause des \expandafter. Une fois qu'ils auront disparu, tu retrouveras la ligne \def\liste{<ancien contenu> <nouveau contenu>};
    • \meaning permet de voir de quoi est composée la macro, rien de plus. Assez pratique pour savoir si une commande est purement développable. Si tu obtiens des commandes, elle ne l'est pas, si tu obtiens que tu texte, elle l'est (le but étant qu'elle le soit, sous peine d'avoir des problèmes comme dans ton second message).


    Pour ton problème, cela vient du fait que \textbf (et toutes commandes de changement de fonts) ne sont pas purement développables. Ainsi, deux solutions s'offrent à toi :

    • Utiliser la commande \noexpand devant toutes les commandes non-purement développables. Cela donnerai :

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      \ajoute{ \noexpand\textbf{\titi}};
      L'avantage est que la macro reste développable en dehors de \textbf. En effet, la macro \titi a été développée, c'est directement son texte de remplacement qui est passé en argument de la commande \textbf (observable avec \meaning\liste).
    • Créer une commande qui ne développe pas les arguments qui lui sont donnés (plus simple à comprendre, mais moins propre) :

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      \def\ajoute#1{%
      	\expandafter\def\expandafter\liste\expandafter{\liste #1}%
      }
      L'avantage est que tu n'as pas à te soucier de savoir si la macro est développable ou non, mais le contenu de \liste ne l'est pas. C'est la commande \titi qui est en argument de la commande \textbf et non son texte de remplacement. Cela peut poser des problèmes si tu redéfinis \titi plus loin dans ton code. Exemple (pdflatex) :

      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
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      % !TEX encoding = UTF-8 Unicode
      % !TEX TS-program = pdfLaTeX
       
      \documentclass[french, a4paper, 12pt, oneside]{article}
       
      \usepackage[utf8]{inputenc}
      \usepackage[T1]{fontenc}
      \usepackage{geometry}
      \usepackage{babel}
       
       
      \makeatletter
       
      \def\liste{}
       
      \def\ajoute#1{%
      	\expandafter\def\expandafter\liste\expandafter{\liste #1}%
      }
       
      \makeatother
       
      \begin{document}
       
      	Contenu de \verb+\liste+: \liste;
       
      	Ajoute « toto » à \verb+\liste+ \ajoute{toto};
       
      	Contenu de \verb+\liste+: \liste;
       
      	\def\titi{titi}
      	Ajoute « titi » à \verb+\liste+ \ajoute{ \titi};
       
      	Contenu de \verb+\liste+: \liste;
       
      	\def\titi{tata}
      	Ajoute « tata » à \verb+\liste+ \ajoute{ \titi};
       
      	Contenu de \verb+\liste+: \liste;
       
      	Contenu de la macro \verb+\liste+: \meaning\liste
       
      \end{document}
      J'espère avoir répondu a tes questions
    La FAQ apporte souvent la solution aux problèmes
    Avant de demander de l'aide, pensez à faire un ECM ! Un problème bien expliqué est un problème à moitié résolu .

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 9
    Points : 5
    Points
    5
    Par défaut
    Putaing !! ça c'est de la réponse !! Quand je pense que les utilisateurs de LaTeX sont des profs de math et des doctorants et qu'un jeunot comme toi fait une réponse de cette qualité, ça fait plaisir !

    En tout cas, je me rends compte que je sais (basiquement) utiliser LaTeX, mais que je ne connais rien de ce qu'il y a derrière !! merci pour les explication d'\expandafter, va falloir retravailler un peu tout ça mais c'est déjà beaucoup plis clair !

    Du coup, je pense que ces fonctions resteront dans ma boite à outils :


    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    \makeatletter
    % version a 2 arguments sale
    \newcommand{\ajouteB}[2]{%
    	\expandafter\def\expandafter#1\expandafter{#1 #2}%
    }
     
     
     
    % version a 2 arguments moins sale mais moins pratique
    \newcommand{\ajouteA}[2]{%
    	\edef\temp@a{#2}%
    	\expandafter\expandafter\expandafter\def%
    	\expandafter\expandafter\expandafter#1%
    	\expandafter\expandafter\expandafter{\expandafter#1\temp@a}%
    }
    \makeatother
     
    \begin{document}
    	% une fonction bien compliquee
    	\def\titi#1{#1}
    	\def\titiB#1{\fbox{\makebox[3cm]{$\sqrt{0+0}$ \textit{\textbf{#1}}}}}
     
     
    	% version a 2 arguments sale
    	\def\listeB{}
    	\ajouteB{\listeB}{\titi{toto1}}
    	\ajouteB{\listeB}{\titiB{toto2}}
    	\ajouteB{\listeB}{\textit{\Large toto3}}
     
    	Version 2 arguments sale : \hfill \listeB
     
    	Développement Version 2 argument : \meaning\listeB
     
    	% version a 2 arguments moins sale
    	\def\listeA{}
    	\ajouteA{\listeA}{\titi{toto1}}
    	\ajouteA{\listeA}{\noexpand\titiB{toto2}}
    	\ajouteA{\listeA}{\noexpand\textit{\noexpand\Large toto3}}
     
    	Version 2 arguments moins sale : \hfill \listeA
     
    	Développement Version 2 argument moins sale : \meaning\listeA
     
    \end{document}
    En revanche, je ne comprends pas pourquoi celle ci ne marche pas... fort probablement encore des problèmes de \expandafter ... à cause de la virgule mise en séparateur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    \def\listeC{}
    \def\ajouteC#1{%
    	\edef\temp@a{#1}%
    	\expandafter\expandafter\expandafter\def%
    	\expandafter\expandafter\expandafter\listeC%
    	\expandafter\expandafter\expandafter{\expandafter\listeC,\temp@a}%
    }
    Merci encore !

  7. #7
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    344
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Haute Vienne (Limousin)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2014
    Messages : 344
    Points : 561
    Points
    561
    Par défaut
    Putaing !! ça c'est de la réponse !! Quand je pense que les utilisateurs de LaTeX sont des profs de math et des doctorants et qu'un jeunot comme toi fait une réponse de cette qualité, ça fait plaisir !
    Merci beaucoup, ça c'est du remerciement

    En tout cas, je me rends compte que je sais (basiquement) utiliser LaTeX, mais que je ne connais rien de ce qu'il y a derrière !! merci pour les explication d'\expandafter, va falloir retravailler un peu tout ça mais c'est déjà beaucoup plis clair !
    LaTeX n'est pas compliqué à utiliser, tout ça, c'est du TeX. Ça devient compliqué lorsqu'on commence à attaquer les commandes de base de TeX.

    En revanche, je ne comprends pas pourquoi celle ci ne marche pas... fort probablement encore des problèmes de \expandafter ... à cause de la virgule mise en séparateur
    Exactement. En disant que \expandafter saute la commande suivante et développe celle encore après, j'ai fait un abus de langage. En réalité, il saute le token suivant et développe celui d'après. Un token est une entité, c'est-à-dire une commande, une lettre, un chiffre, un sybmbole ({, , dans ton cas). Dans ton dernier code, il faut donc rajouter un \expandafter après \listeC et avant la virgule pour sauter la , et développer \temp@a.

    J'en ai profité aussi pour améliorer ta commande avec la virgule en introduisant un test pour éviter d'avoir une virgule au début de la chaine :

    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
    19
    \let\liste\@empty
     
    \def\iffirstitem#1{%
    	\csname%
    		@\ifx#1\@empty
    			first%
    		\else
    			second%
    		\fi
    		oftwo%
    	\endcsname%
    }
     
    \def\ajoute#1{%
    	\edef\temp@a{\iffirstitem\liste{}{,}#1}%
    	\expandafter\expandafter\expandafter\def%
    	\expandafter\expandafter\expandafter\liste%
    	\expandafter\expandafter\expandafter{\expandafter\liste\temp@a}%
    }
    Quelques explications :

    • La commande \iffirstitem prend une commande en argument qui est la commande à tester. Si elle est vide (= \@empty, elle va afficher le premier argument et manger le second. Sinon l'inverse;
    • En plaçant le test dans la commande \temp@a, le \edef va développer totalement le test et afficher uniquement le résultat (rien ou la virgule).


    Passons au fonctionnement du test :

    • la paire de commande \csname ...\endcsname permet de transformer le contenu en commande. C'est-à-dire que écrire \csname toto\endcsname revient à écrire \toto (LaTeX met une commande semblable à disposition \@nameuse);
    • Le test \ifx compare deux commandes, rien de très compliqué ;
    • le résultat du test est donc la commande \@firstoftwo si la liste est vide, sinon il retourne \@secondoftwo. Ces deux commandes sont définies par LaTeX comme cela :

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      \def\@firstoftwo#1#2{#1}
      \def\@secondoftwo#1#2{#2}
    La FAQ apporte souvent la solution aux problèmes
    Avant de demander de l'aide, pensez à faire un ECM ! Un problème bien expliqué est un problème à moitié résolu .

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

Discussions similaires

  1. [COMPILATION][RECURSIVE] outil ?
    Par narmataru dans le forum Build
    Réponses: 6
    Dernier message: 14/01/2009, 16h05
  2. problème avec une procédure recursive
    Par vbcasimir dans le forum SQL
    Réponses: 1
    Dernier message: 10/06/2005, 17h38
  3. doc en latex
    Par alexis_ dans le forum Bibliothèques tierces
    Réponses: 2
    Dernier message: 09/05/2005, 10h06
  4. [C++] Creer des repertoires de facon recursive
    Par barthelv dans le forum Windows
    Réponses: 2
    Dernier message: 25/04/2005, 16h12
  5. Exploitation d'une table possédant une relation recursive
    Par VincentR dans le forum Langage SQL
    Réponses: 2
    Dernier message: 26/08/2004, 12h07

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