\expandafter, \csname issue related to test for macro being defined
You should use \ifcsname
... \endcsname
instead.
Note that \csname
... \endcsname
makes the undefined control sequence to be \relax
. See TeXbook Exercise 7.7:
When
\csname
is used to define a control sequence for the first time, that control sequence is made equivalent to\relax
until it is redefined.
You can test a macro like this:
\documentclass{article}
\usepackage{pgffor}
\usepackage{etoolbox}
\begin{document}
\def\ConditionH{}
\foreach \i in {G, H}{
\ifcsname Condition\i\endcsname
\textbackslash Condition\i\ is defined\par
\else
\textbackslash Condition\i\ is not defined\par
\fi
}
\hrule
\foreach \i in {G, H}{% Using etoolbox
\ifcsdef{Condition\i}{%
\textbackslash Condition\i\ is defined\par
}{
\textbackslash Condition\i\ is not defined\par
}
}
\end{document}
In addition to Leo's answer, without e-TeX the usual test for an undefined control sequence is
\def\ifundefined#1{%
\begingroup\expandafter\expandafter\expandafter\endgroup
\expandafter\ifx\csname #1\endcsname\relax
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
This works by doing the \csname
... \endcsname
inside a group and testing if the meaning of the name we want is equal to \relax
. The group means that if the control sequence was undefined then it is only made into \relax
within the test, and not globally. The downside is that this test is not expandable. Of course, it cannot tell the difference between an undefined control sequence and one that is deliberately equal to \relax
. (The \expandafter
s here make the \csname
happen before the \ifx
, which itself takes place before the \endgroup
.)
A side note. In the LaTeX2e kernel, \@ifundefined
does not use the grouping approach, so that it has an expandable test. That means that each time you use \@ifundefined
with a previously-undefined control sequence, it does end up defined as \relax
.
In addition to the other, more relevant answers, I want to mention that your second code block uses \expandafter
redundantly. The result of \expandafter\csname Condition\i\endcsname
is just \csname Condition\i\endcsname
, since the "C" is expanded before \csname
. As it turns out, \csname
itself continues the expansion and eventually gets \i
, but for example something like \expandafter\toks0={\i}
will backfire (it expands the 0, not the \i
).
It's possible you intended to use \expandafter
as an "execute this" command, as though its function were: \expandafter\a\b
first expands \b
, then expands \a
. In fact, all it does is expand \b
"in place", without touching \a
; if \a
does expand, that is because TeX's own "mouth" continues processing the input, expanding as it goes. If \a
is not expandable but executable, then it is executed, unless that is inhibited, like in \edef
. For example, \edef\macro{\def\a{a}\a}
does not define \macro=a
, but rather gives an error (assuming \a
was not defined already) since it doesn't expand \def
and thus, doesn't know that the \a
after it is not intended to be expanded. No amount of \expandafter
s will change this.
If that was not your intention, please take my lecture to be directed at the audience.