Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
2_programmation:macros:cette_commande_est_elle_definie [2018/05/25 00:02]
joseph.wright
2_programmation:macros:cette_commande_est_elle_definie [2021/09/27 23:41] (Version actuelle)
bdumont Traduction et remaniement pour mettre les solutions modernes et fiables en premier
Ligne 1: Ligne 1:
---- +====== Comment tester si une commande est définie? ======
-section: Macro programming +
-subsection: ''​Generic''​ macros and techniques +
-permalink: /​FAQ-isdef.html +
-date: 2014-06-10 +
----+
  
-# Is this command defined?+===== En TeX =====
  
-Macro sets from the earliest days of TeX programming may be +Le programme <​latex>​\TeX{}</​latex>​ originalécrit par Donald Knuthne définit pas de commandes dédiées à cette tâcheHeureusement,​ [[1_generalites:​glossaire:​qu_est_ce_que_etex|ε-TeX]] définit deux primitives supplémentaires :​
-observed to test whether commands exist by using +
-`\ifx` `\``_command_` `\undefined` &​lsaquo;​_stuff_&​rsaquo;​ &​hellip;​ +
-(which of course actually tests that the command _doesn'​t_ +
-exist). ​ LaTeX programmers can make use of the internal command +
-  `ifundefined{cmd name}{action1}{action2}` +
-which executes `action1` if the command is undefinedand +
-`action2` if it is defined +
-(_cmd name_ is the command name onlyomitting the `\` character).+
  
-The `ifundefined` command is based on the sequence +  * ''​\ifdefined''​ 
-```latex +  * ''​\ifcsname ​cmd name\endcsname'​'
-\expandafter \ifx \csname ​cmd name\endcsname ​\relax +
-``` +
-which relies on the way `\csname` works: if the command doesn'+
-exist, it simply creates it as an alias for `\relax`.+
  
-Sowhat is wrong with these techniques?+Les deux commandes utilisées dans l'​exemple qui suit produisent le même effet :
  
-Using `\undefined` blithely assumes that the command is indeed not +<code latex>
-defined. ​ This isn't entirely safe; one could make the name more +
-improbable, but that may simply make it more difficult to spot a +
-problem when things go wrong. ​ LaTeX programmers who use the +
-technique will typically employ `undefined`,​ adding a single +
-level of obscurity. +
- +
-The `ifundefined` mechanism has the unfortunate property of +
-polluting the name space: each test that turns out undefined adds a +
-name to the set TeX is holding, and often all those `\relax` +
-names serve no purpose whatever. ​ Even so (sadly) there are places in +
-the code of LaTeX where the existence of the `\relax` is relied +
-upon, after the test, so we can't get away from `ifundefined` +
-altogether. +
- +
-David Kastrup offers the (rather tricky) +
-```latex +
-{\expandafter}\expandafter\ifx \csname cmd name\endcsname\relax ... +
-``` +
-which ''​creates''​ the `\relax`-command inside the group of the first +
-`\expandafter`,​ therefore forgets it again once the test is done. +
-The test is about as good as you can do with macros. +
- +
-The [&​epsilon;​-TeX system](FAQ-etex.md) system comes to our help here: it +
-defines two new primitives:​ +
-   +
- +
--  `\ifdefined`,​ which tests whether a thing is defined (the +
-    negative of comparing with `\undefined`,​ as it were), and +
--  `\ifcsname` `cmd name``\endcsname`,​ which does the +
-    negative of `ifundefined` without the `\relax`-command +
-    side-effect. +
- +
-So, in an &​epsilon;​-TeX-based system, the following two conditional clauses do +
-the same thing: +
-```latex+
 \ifdefined\foo \ifdefined\foo
   \message{\string\foo\space is defined}%   \message{\string\foo\space is defined}%
Ligne 74: Ligne 22:
   \message{no command \string\foo}%   \message{no command \string\foo}%
 \fi \fi
-``` +</​code>​ 
-However, after using the LaTeX + 
-`ifundefined{foo}`&​hellip;​, the conditionals will detect the +However, after using the original ​LaTeX ''​\@ifundefined{foo}...''​, 
-command as ''​existing'' ​(since it has been `\letto `\relax`); +the conditionals will detect the command as "existing
-so it is important not to mix mechanisms for detecting the state of a +(since it has been ''​\let'' ​to ''​\relax''​) ; so it is important 
-command.+not to mix mechanisms for detecting the state of a command
 + 
 +===== En LaTeX ===== 
 + 
 +Quand on programme en <​latex>​\LaTeX{}</​latex>,​ on peut directement utiliser 
 +''​\@ifundefined{<//​cmd name//>​}{<//​action1//>​}{<//​action2//>​}'',​ 
 +qui exécute ''<//​action1//>''​ si la commande **n'​**est **pas** définie, 
 +et ''<//​action2//>''​ dans le cas contraire 
 +(''<//​cmd name//>''​ est le nom de la commande tout nu, **sans son antislash** ''​\''​). 
 + 
 +Si vous utilisez une version de <​latex>​\LaTeX{}</​latex>​ antérieure à 2018, il faut éviter de mélanger du code qui utilise les primitives d'​ε-TeX avec du code qui utilise ''​\@ifundefined''​ (voir ci-dessous pourquoi). Comme cela peut se produire d'une extension à l'​autre,​ vous n'​êtes jamais à l'abri d'une erreur... 
 + 
 +Notez également que, même après 2018, <​latex>​\LaTeX{}</​latex>​ va toujours renvoyer "​vrai"​ si l'on utilise ''​\@ifundefined''​ avec une commande définie comme un alias de ''​\relax''​. 
 + 
 +===== Un peu d'​histoire ===== 
 + 
 +On trouve dans d'​anciennes macros écrites en <​latex>​\TeX{}</​latex>​ le procédé suivant 
 +pour tester l'​existence d'une commande ''<//​commande//>'':​ 
 + 
 +''​\ifx\<//​commande//>​\undefined<//​code à exécuter//>''​ 
 + 
 +(Ceci exécute le code si la commande **n'​**existe **pas**, bien sûr.) 
 + 
 +Le fonctionnement de cette commande repose sur le principe que ''​\undefined''​ n'est jamais défini (donc elle est égale à une autre commande non définie). Le problème est qu'il ne s'agit que d'une convention qui peut être ignorée par un autre auteur de macros : il y a donc toujours un risque que cette macro soit définie dans une extension chargée par l'​utilisateur... Utiliser ''​\@undefined'',​ comme on peut le voir dans certaines macros <​latex>​\LaTeX{}</​latex>,​ ne fait que déplacer le problème. 
 + 
 +La macro ''​\@ifundefined'',​ elle, est définie dans le noyau de <​latex>​\LaTeX{}</​latex>,​ ce qui permet d'​éviter ce problème. Cependant, avant 2018, elle était définie de la manière suivante :​ 
 + 
 +<code latex> 
 +\expandafter \ifx \csname cmd name\endcsname \relax 
 +</​code>​ 
 + 
 +Elle utilisait la propriété suivante de ''​\csname''​ :​ 
 +si la commande n'​existe pas, elle est créée comme alias de ''​\relax''​. 
 +Cette approche présente deux inconvénients :​  
 + 
 +  * Chaque utilisation de ''​\@ifundefined''​ avec un nom de commande qui n'​existe pas crée cette commande, définie comme identique à ''​\relax''​ ; si cette commande n'est pas redéfinie ensuite, elle est conservée inutilement en mémoire par le moteur <​latex>​\TeX{}</​latex>​ ; 
 +  * Si le même nom de commande est testé ensuite avec la primitive ε-TeX ''​\ifdefined''​ (par exemple dans le code d'une autre extension), le résultat sera un faux positif, car cette primitive considère aussi comme définie la commande ''​\relax''​ et ses alias. 
 + 
 +Avant que ''​\@ifundefined''​ ne soit redéfinie dans le noyau <​latex>​\LaTeX{}</​latex>​ pour être basée sur la primitive ε-TeX ''​\ifdefined'',​ David Kastrup a proposé la solution suivante :​ 
 + 
 +<code latex> 
 +{\expandafter}\expandafter\ifx \csname cmd name\endcsname\relax ... 
 +</​code>​ 
 + 
 +La commande testée est créée et définie comme ''​\relax''​ à l'​intérieur du groupe dans lequel est inclus le premier 
 +''​\expandafter''​ :​ elle n'est donc pas conservée en mémoire après l'​exécution de ''​\@ifundefined''​.
  
-Since most distributions nowadays use &​epsilon;​-TeX as their base executable +----- 
-for most packages, these two primitives may be expected appear widely +//Source:// [[faquk>​FAQ-isdef|Is this command defined?]]
-in new macro packages.+
  
 +{{htmlmetatags>​metatag-keywords=(LaTeX,​programmation LaTeX,​tester si une macro est définie,​savoir si une commande est définie)
 +metatag-og:​title=(Is this command defined?)
 +metatag-og:​site_name=(FAQ LaTeX francophone)
 +}}
  
2_programmation/macros/cette_commande_est_elle_definie.1527199361.txt.gz · Dernière modification: 2018/05/25 00:02 (modification externe)
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0