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)
que “cria” o comando{\expandafter}\expandafter\ifx \csname cmd name\endcsname\relax ...
\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
.
No entanto, depois de usar o\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
\@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!