RAW HTWL
 
Macros récursives en RAW HTWL

retour au sommaire général


On appelle macro récursive une macro qui fait référence à elle-même dans sa définition. Ce genre de macro ne peut être défini qu'avec \def, jamais avec \let.


1. Risques

La définition de macro suivante est très dangereuse, puisque son développement fait appel à elle-même, donc si on l'appelait une fois, elle s'appellerait une autre fois, puis une autre, et ainsi de suite. Cela provoquerait une saturation de la mémoire, et un plantage de RAW HTWL, voire du Mac.

\def \infinite_loop
{
    \infinite_loop
}



2. Conditions d'arrêt

Pour arrêter à un moment ou un autre le développement d'une macro récursive, il faut employer un test, dit condition d'arrêt :

\def \compteur { 8 }

\def \compte_a_rebours
{
    \if { \compteur <= 0 }
    {
        FIN
    }
    \else
    {
        TOP \compteur
        \let \compteur { \num { \compteur-1 } }
        \compte_a_rebours
    }
}

Quand on l'appelle, cette macro \compte_a_rebours se lance une première fois : comme \compteur est supérieur à zéro, elle affiche « TOP \compteur », c'est-à-dire « TOP 8 », décrémente le compteur, et s'appelle elle-même.

Lors de ce deuxième appel, comme \compteur est encore supérieur à zéro, elle affiche « TOP \compteur », c'est-à-dire cette fois-ci « TOP 7 », décrémente le compteur, et s'appelle de nouveau elle-même.

Au fur et à mesure de ses développements imbriqués, la macro affiche « TOP 6 », puis « TOP 5 », « TOP 4 », « TOP 3 », « TOP 2 », puis… s'appelle de nouveau après avoir fait baisser le compteur.

Cette fois, quand elle s'exécute, le compteur est à < 1 >. Il est supérieur à zéro, donc elle affiche « TOP 1 », puis décrémente le compteur et s'appelle elle-même.

Lors de ce nouvel appel, elle s'aperçoit que le compteur est égal à zéro. Elle affiche donc « FIN » et… ne s'appelle plus ! Le développement est alors terminé.

 
Surtout, ne pas oublier d'utiliser la primitive \num quand il le faut ! Dans certains cas, ça peut tout changer ! Exemple : la condition \if { \num { 2 - 0 } <= 0 } est équivalente à \if { 2 <= 0}, qui est fausse, tandis que la condition \if { 2 - 0 <= 0 } où on a oublié le \num, est équivalente à \if { 2 - ( 0 <= 0 ) }, donc à \if { 2 - 1 }, qui est une condition vraie (\if { 1 }).


3. Récursivité et arguments

Dans l'exemple précédent, on s'appuyait sur une variable \compteur externe à la macro. Voyons maintenant un compte à rebours codé sans variable externe :

\def \compteur_autonome #debut
{
    \if { #debut <= 0 }
    {
        FIN
    }
    \else
    {
        TOP #debut

        \compteur_autonome { \num { #debut - 1 } }
    }
}

\compteur_autonome { 8 }

On passe en argument le début du compte à rebours.


4. Nombre d'arguments illimité

Tout comme TEX, RAW HTWL permet grâce à des astuces, de passer aux macros un nombre illimité d'arguments. Cela est utile quand on veut coder une table ou une liste dont le nombre d'éléments pourra varier au cours de l'évolution du site.

On utilise pour cela des arguments avec séparateurs :

\def \lignes_centrees_infinies #texte \stop
{
    \ifvoid { #texte }
    {

    }
    \else
    {
        <TR><TD ALIGN="center"> #texte </TD></TR>

        \lignes_centrees_infinies
    }
}

On voit que l'arrêt se décide sur le fait que l'argument passé est vide ou non.

Cette macro s'utilise ainsi :

<TABLE BORDER="1" CELLPADDING="4" CELLSPACING="0">

\lignes_centrees_infinies

    Bonjour, ceci est la première ligne \stop
    Voici la seconde \stop
    Et la troisième \stop
    Je peux en mettre autant que je veux \stop
    Du moment que \stop
    Je m'arrête comme \stop
    il faut \stop
    \stop

</TABLE>

On termine bien l'appel à la macro par un argument vide.


Se reporter aussi à la présentation de \ifvoid, et aux exemples.


5. Poursuivre la navigation

retour au sommaire général