Conjuntos de macros dos primeiros dias da programação TeX podem ser testados para verificar os comandos existem usando
(que, evidentemente, verifica que o comando não existe). Programadores do LaTeX podem fazer uso do comando interno\ifx\command\undefined‹stuff› …
que executa a action1 se o comando estiver indefinido, e a action2 se ele estiver definido (cmd name é apenas o nome do comando, omitindo o caractere ‘\@ifundefined{cmd name}{action1}{action2}
\’).
O comando \@ifundefined está baseado na sequência
que se baseia na maneira como o\expandafter \ifx \csname cmd name\endcsname \relax
\csname funciona: se o comando não existir, ele simplesmente o cria como um alias do \relax.
Então, o que há de errado com essas técnicas?
Usar o \undefined é assumir levianamente que o comando está, de fato, não definido. Isso não é totalmente seguro; poder-se-ia usar um nome mais improvável, mas isso pode simplesmente dificultar a identificação de um problema quando as coisas derem errado. Programadores do LaTeX que usam a técnica normalmente empregam \@undefined, adicionando um único nível de obscuridade.
O mecanismo de \@ifundefined tem a infeliz propriedade de poluir o “namespace”: cada teste que resulta indefinido adiciona um nome ao conjunto do TeX e, muitas vezes, todos aqueles nomes “\relax”
não servem para nada. Mesmo assim (infelizmente), existem lugares no código do LaTeX onde se depende da existência do \relax, após o teste, por isso não podemos fugir do \@ifundefined
completamente.
David Kastrup oferece o (bem complicado)
{\expandafter}\expandafter\ifx \csname cmd name\endcsname\relax ...
que “cria” o comando \relax dentro do grupo do primeiro
\expandafter, e o esquece novamente depois que o teste é feito. O teste é tão bom quanto o que se pode fazer com macros.
O sistema e-TeX vem nos socorrer aqui: ele define duas novas primitivas:
\ifdefined, que testa se uma coisa está definida (o negativo de comparar com o \undefined), e
\ifcsname cmd name\endcsname, que faz o negativo de \@ifundefined sem o efeito colateral do comando \relax.
\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
No entanto, depois de usar o \@ifundefined{foo}…, do LaTeX, as condicionais vão detectar o comando como “existente” (desde que ele tenha sido \let para o \relax); por isso, é importante não misturar mecanismos para detectar o estado de um comando.
Como a maioria das distribuições hoje em dia usa o e-TeX como base executável para a maioria dos pacotes, é esperado que essas duas primitivas apareçam amplamente em novos pacotes de macros.
This question on the Web: http://latex.net.br/faq/FAQ-isdef.html
Do you have any question? Ask on: latex.net.br - we love qood questions!