====== Comment tester si une commande est définie? ======
===== En TeX =====
Le programme \TeX{} original, écrit par Donald Knuth, ne définit pas de commandes dédiées à cette tâche. Heureusement, [[1_generalites:glossaire:qu_est_ce_que_etex|ε-TeX]] définit deux primitives supplémentaires :
* ''\ifdefined''
* ''\ifcsname cmd name\endcsname''
Les deux commandes utilisées dans l'exemple qui suit produisent le même effet :
\ifdefined\foo
\message{\string\foo\space is defined}%
\else
\message{no command \string\foo}%
\fi
%
\ifcsname foo\endcsname
\message{\string\foo\space is defined}%
\else
\message{no command \string\foo}%
\fi
However, after using the original LaTeX ''\@ifundefined{foo}...'',
the conditionals will detect the command as "existing"
(since it has been ''\let'' to ''\relax'') ; so it is important
not to mix mechanisms for detecting the state of a command.
===== En LaTeX =====
Quand on programme en \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{} 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{} 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 \TeX{} 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{}, ne fait que déplacer le problème.
La macro ''\@ifundefined'', elle, est définie dans le noyau de \LaTeX{}, ce qui permet d'éviter ce problème. Cependant, avant 2018, elle était définie de la manière suivante :
\expandafter \ifx \csname cmd name\endcsname \relax
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 \TeX{} ;
* 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{} pour être basée sur la primitive ε-TeX ''\ifdefined'', David Kastrup a proposé la solution suivante :
{\expandafter}\expandafter\ifx \csname cmd name\endcsname\relax ...
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''.
-----
//Source:// [[faquk>FAQ-isdef|Is this command defined?]]
{{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)
}}